From f84d7fa62e0b72b7b987f556a78cf47b4fe38efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=9C=E7=8E=89=E7=90=A6?= <7507756+jiang_yuqi@user.noreply.gitee.com> Date: Sat, 17 Aug 2024 12:11:19 +0800 Subject: [PATCH] jiangyuqi init commit --- LICENSE | 21 + README.md | 134 + bin/clean.bat | 12 + bin/package.bat | 12 + bin/run-auth.bat | 14 + bin/run-gateway.bat | 14 + bin/run-modules-file.bat | 14 + bin/run-modules-gen.bat | 14 + bin/run-modules-job.bat | 14 + bin/run-modules-system.bat | 14 + bin/run-monitor.bat | 14 + docker/copy.sh | 41 + docker/deploy.sh | 67 + docker/docker-compose.yml | 140 + docker/mysql/db/readme.txt | 1 + docker/mysql/dockerfile | 7 + docker/nacos/conf/application.properties | 32 + docker/nacos/dockerfile | 7 + docker/nginx/conf/nginx.conf | 36 + docker/nginx/dockerfile | 15 + docker/redis/conf/redis.conf | 1 + docker/redis/dockerfile | 13 + docker/ruoyi/auth/dockerfile | 15 + docker/ruoyi/auth/jar/readme.txt | 1 + docker/ruoyi/gateway/dockerfile | 15 + docker/ruoyi/gateway/jar/readme.txt | 1 + docker/ruoyi/modules/file/dockerfile | 15 + docker/ruoyi/modules/file/jar/readme.txt | 1 + docker/ruoyi/modules/gen/dockerfile | 15 + docker/ruoyi/modules/gen/jar/readme.txt | 1 + docker/ruoyi/modules/job/dockerfile | 15 + docker/ruoyi/modules/job/jar/readme.txt | 1 + docker/ruoyi/modules/system/dockerfile | 15 + docker/ruoyi/modules/system/jar/readme.txt | 1 + docker/ruoyi/visual/monitor/dockerfile | 15 + docker/ruoyi/visual/monitor/jar/readme.txt | 1 + docsql/image.png | Bin 0 -> 1031521 bytes docsql/nacos配置/yz-config.sql | 309 + docsql/quartz.sql | 174 + docsql/ry-order.sql | 37 + docsql/ry_cloud.sql | 695 ++ docsql/分库分表/ry_seata_20210128.sql | 80 + docsql/分库分表/seata_account.sql | 57 + docsql/分库分表/seata_order.sql | 62 + docsql/分库分表/seata_product.sql | 58 + pom.xml | 331 + yanzhu-api/pom.xml | 22 + yanzhu-api/yanzhu-api-system/pom.xml | 28 + .../yanzhu/system/api/RemoteFileService.java | 29 + .../yanzhu/system/api/RemoteLogService.java | 41 + .../yanzhu/system/api/RemoteUserService.java | 43 + .../com/yanzhu/system/api/domain/SysDept.java | 203 + .../yanzhu/system/api/domain/SysDictData.java | 176 + .../yanzhu/system/api/domain/SysDictType.java | 96 + .../com/yanzhu/system/api/domain/SysFile.java | 50 + .../system/api/domain/SysLogininfor.java | 102 + .../yanzhu/system/api/domain/SysOperLog.java | 255 + .../com/yanzhu/system/api/domain/SysRole.java | 241 + .../com/yanzhu/system/api/domain/SysUser.java | 323 + .../factory/RemoteFileFallbackFactory.java | 35 + .../api/factory/RemoteLogFallbackFactory.java | 42 + .../factory/RemoteUserFallbackFactory.java | 41 + .../yanzhu/system/api/model/LoginUser.java | 150 + ...ot.autoconfigure.AutoConfiguration.imports | 3 + yanzhu-auth/pom.xml | 117 + .../com/yanzhu/auth/RuoYiAuthApplication.java | 31 + .../auth/controller/TokenController.java | 78 + .../java/com/yanzhu/auth/form/LoginBody.java | 39 + .../com/yanzhu/auth/form/RegisterBody.java | 11 + .../yanzhu/auth/service/SysLoginService.java | 143 + .../auth/service/SysPasswordService.java | 85 + .../auth/service/SysRecordLogService.java | 48 + yanzhu-auth/src/main/resources/banner.txt | 10 + yanzhu-auth/src/main/resources/bootstrap.yml | 25 + yanzhu-auth/src/main/resources/logback.xml | 74 + yanzhu-common/pom.xml | 30 + yanzhu-common/yanzhu-common-core/pom.xml | 117 + .../yanzhu/common/core/annotation/Excel.java | 183 + .../yanzhu/common/core/annotation/Excels.java | 18 + .../common/core/annotation/RateLimiter.java | 37 + .../common/core/constant/CacheConstants.java | 75 + .../common/core/constant/Constants.java | 130 + .../common/core/constant/GenConstants.java | 117 + .../common/core/constant/HttpStatus.java | 94 + .../core/constant/ScheduleConstants.java | 50 + .../core/constant/SecurityConstants.java | 55 + .../core/constant/ServiceNameConstants.java | 34 + .../common/core/constant/TokenConstants.java | 25 + .../common/core/constant/UserConstants.java | 80 + .../common/core/constant/WechatConstants.java | 14 + .../modules/ManageCacheConstants.java | 22 + .../core/context/SecurityContextHolder.java | 98 + .../java/com/yanzhu/common/core/domain/R.java | 115 + .../yanzhu/common/core/enums/IsDelEnums.java | 31 + .../yanzhu/common/core/enums/LimitType.java | 19 + .../yanzhu/common/core/enums/OwnerType.java | 30 + .../core/enums/RegisterChannelEnums.java | 28 + .../common/core/enums/SignUpTypeEnums.java | 31 + .../yanzhu/common/core/enums/TaskStatus.java | 31 + .../yanzhu/common/core/enums/UserStatus.java | 30 + .../core/exception/CaptchaException.java | 16 + .../core/exception/CheckedException.java | 31 + .../core/exception/DemoModeException.java | 15 + .../core/exception/GlobalException.java | 58 + .../core/exception/InnerAuthException.java | 16 + .../core/exception/PreAuthorizeException.java | 15 + .../core/exception/ServiceException.java | 74 + .../common/core/exception/UtilException.java | 26 + .../exception/auth/NotLoginException.java | 16 + .../auth/NotPermissionException.java | 23 + .../core/exception/auth/NotRoleException.java | 23 + .../core/exception/base/BaseException.java | 79 + .../core/exception/file/FileException.java | 19 + .../FileNameLengthLimitExceededException.java | 16 + .../file/FileSizeLimitExceededException.java | 16 + .../exception/file/FileUploadException.java | 61 + .../file/InvalidExtensionException.java | 80 + .../core/exception/job/TaskException.java | 34 + .../user/CaptchaExpireException.java | 16 + .../core/exception/user/UserException.java | 18 + .../user/UserPasswordNotMatchException.java | 16 + .../yanzhu/common/core/text/CharsetKit.java | 86 + .../com/yanzhu/common/core/text/Convert.java | 1006 +++ .../yanzhu/common/core/text/StrFormatter.java | 92 + .../yanzhu/common/core/utils/DateUtils.java | 183 + .../common/core/utils/ExceptionUtil.java | 39 + .../yanzhu/common/core/utils/JwtUtils.java | 123 + .../com/yanzhu/common/core/utils/NoUtils.java | 37 + .../yanzhu/common/core/utils/PageUtils.java | 35 + .../common/core/utils/ServletUtils.java | 333 + .../yanzhu/common/core/utils/SpringUtils.java | 114 + .../yanzhu/common/core/utils/StringUtils.java | 561 ++ .../common/core/utils/bean/BeanUtils.java | 110 + .../core/utils/bean/BeanValidators.java | 24 + .../common/core/utils/file/FileTypeUtils.java | 95 + .../common/core/utils/file/FileUtils.java | 261 + .../common/core/utils/file/ImageUtils.java | 84 + .../common/core/utils/file/MimeTypeUtils.java | 59 + .../common/core/utils/html/EscapeUtil.java | 167 + .../common/core/utils/html/HTMLFilter.java | 570 ++ .../common/core/utils/http/HttpHelper.java | 56 + .../common/core/utils/http/HttpUtils.java | 330 + .../yanzhu/common/core/utils/ip/IpUtils.java | 382 + .../core/utils/poi/ExcelHandlerAdapter.java | 19 + .../common/core/utils/poi/ExcelUtil.java | 1486 ++++ .../core/utils/reflect/ReflectUtils.java | 411 + .../yanzhu/common/core/utils/sign/Base64.java | 291 + .../yanzhu/common/core/utils/sql/SqlUtil.java | 61 + .../common/core/utils/uuid/IdUtils.java | 49 + .../yanzhu/common/core/utils/uuid/Seq.java | 86 + .../yanzhu/common/core/utils/uuid/UUID.java | 484 ++ .../core/web/controller/BaseController.java | 143 + .../common/core/web/domain/AjaxResult.java | 206 + .../common/core/web/domain/BaseEntity.java | 129 + .../common/core/web/domain/TreeEntity.java | 79 + .../common/core/web/page/PageDomain.java | 101 + .../common/core/web/page/TableDataInfo.java | 85 + .../common/core/web/page/TableSupport.java | 56 + .../java/com/yanzhu/common/core/xss/Xss.java | 27 + .../yanzhu/common/core/xss/XssValidator.java | 34 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + yanzhu-common/yanzhu-common-datascope/pom.xml | 27 + .../datascope/annotation/DataScope.java | 33 + .../datascope/aspect/DataScopeAspect.java | 168 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../yanzhu-common-datasource/pom.xml | 35 + .../common/datasource/annotation/Master.java | 22 + .../common/datasource/annotation/Slave.java | 22 + yanzhu-common/yanzhu-common-log/pom.xml | 27 + .../com/yanzhu/common/log/annotation/Log.java | 51 + .../yanzhu/common/log/aspect/LogAspect.java | 250 + .../common/log/enums/BusinessStatus.java | 20 + .../yanzhu/common/log/enums/BusinessType.java | 59 + .../yanzhu/common/log/enums/OperatorType.java | 24 + .../log/filter/PropertyPreExcludeFilter.java | 24 + .../common/log/service/AsyncLogService.java | 29 + ...ot.autoconfigure.AutoConfiguration.imports | 2 + yanzhu-common/yanzhu-common-mapper/pom.xml | 33 + .../main/java/com/yanzhu/mapper/domain/init | 0 yanzhu-common/yanzhu-common-redis/pom.xml | 33 + .../FastJson2JsonRedisSerializer.java | 49 + .../common/redis/configure/RedisConfig.java | 43 + .../common/redis/service/RedisService.java | 268 + ...ot.autoconfigure.AutoConfiguration.imports | 2 + yanzhu-common/yanzhu-common-seata/pom.xml | 27 + yanzhu-common/yanzhu-common-security/pom.xml | 39 + .../annotation/EnableCustomConfig.java | 31 + .../annotation/EnableRyFeignClients.java | 27 + .../common/security/annotation/InnerAuth.java | 19 + .../common/security/annotation/Logical.java | 20 + .../security/annotation/RequiresLogin.java | 18 + .../annotation/RequiresPermissions.java | 27 + .../security/annotation/RequiresRoles.java | 26 + .../security/aspect/InnerAuthAspect.java | 51 + .../security/aspect/PreAuthorizeAspect.java | 98 + .../common/security/auth/AuthLogic.java | 374 + .../yanzhu/common/security/auth/AuthUtil.java | 167 + .../security/config/ApplicationConfig.java | 22 + .../common/security/config/WebMvcConfig.java | 33 + .../feign/FeignAutoConfiguration.java | 20 + .../feign/FeignRequestInterceptor.java | 54 + .../handler/GlobalExceptionHandler.java | 136 + .../interceptor/HeaderInterceptor.java | 55 + .../common/security/service/TokenService.java | 169 + .../common/security/utils/DictUtils.java | 75 + .../common/security/utils/SecurityUtils.java | 118 + ...ot.autoconfigure.AutoConfiguration.imports | 5 + yanzhu-common/yanzhu-common-swagger/pom.xml | 34 + .../annotation/EnableCustomSwagger2.java | 20 + .../config/SwaggerAutoConfiguration.java | 129 + .../config/SwaggerBeanPostProcessor.java | 54 + .../swagger/config/SwaggerProperties.java | 345 + .../config/SwaggerWebConfiguration.java | 22 + ...ot.autoconfigure.AutoConfiguration.imports | 3 + yanzhu-gateway/pom.xml | 153 + .../gateway/RuoYiGatewayApplication.java | 29 + .../yanzhu/gateway/config/CaptchaConfig.java | 83 + .../yanzhu/gateway/config/GatewayConfig.java | 23 + .../gateway/config/KaptchaTextCreator.java | 75 + .../config/RouterFunctionConfiguration.java | 31 + .../gateway/config/SwaggerProvider.java | 79 + .../config/properties/CaptchaProperties.java | 46 + .../properties/IgnoreWhiteProperties.java | 33 + .../config/properties/XssProperties.java | 48 + .../com/yanzhu/gateway/filter/AuthFilter.java | 135 + .../gateway/filter/BlackListUrlFilter.java | 65 + .../gateway/filter/CacheRequestFilter.java | 87 + .../gateway/filter/ValidateCodeFilter.java | 79 + .../com/yanzhu/gateway/filter/XssFilter.java | 129 + .../handler/GatewayExceptionHandler.java | 56 + .../handler/SentinelFallbackHandler.java | 41 + .../gateway/handler/SwaggerHandler.java | 56 + .../gateway/handler/ValidateCodeHandler.java | 42 + .../gateway/service/ValidateCodeService.java | 23 + .../service/impl/ValidateCodeServiceImpl.java | 119 + yanzhu-gateway/src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 40 + yanzhu-gateway/src/main/resources/logback.xml | 74 + yanzhu-modules/pom.xml | 27 + yanzhu-modules/yanzhu-file/pom.xml | 131 + .../com/yanzhu/file/RuoYiFileApplication.java | 31 + .../com/yanzhu/file/config/MinioConfig.java | 82 + .../yanzhu/file/config/ResourcesConfig.java | 50 + .../file/controller/SysFileController.java | 48 + .../service/FastDfsSysFileServiceImpl.java | 42 + .../yanzhu/file/service/ISysFileService.java | 20 + .../file/service/LocalSysFileServiceImpl.java | 50 + .../file/service/MinioSysFileServiceImpl.java | 45 + .../yanzhu/file/utils/FileUploadUtils.java | 180 + .../yanzhu-file/src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../src/main/resources/logback.xml | 74 + yanzhu-modules/yanzhu-gen/pom.xml | 137 + .../com/yanzhu/gen/RuoYiGenApplication.java | 34 + .../java/com/yanzhu/gen/config/GenConfig.java | 66 + .../yanzhu/gen/controller/GenController.java | 212 + .../java/com/yanzhu/gen/domain/GenTable.java | 370 + .../com/yanzhu/gen/domain/GenTableColumn.java | 374 + .../gen/mapper/GenTableColumnMapper.java | 60 + .../com/yanzhu/gen/mapper/GenTableMapper.java | 83 + .../service/GenTableColumnServiceImpl.java | 69 + .../gen/service/GenTableServiceImpl.java | 522 ++ .../gen/service/IGenTableColumnService.java | 44 + .../yanzhu/gen/service/IGenTableService.java | 121 + .../java/com/yanzhu/gen/util/GenUtils.java | 258 + .../yanzhu/gen/util/VelocityInitializer.java | 34 + .../com/yanzhu/gen/util/VelocityUtils.java | 403 + .../yanzhu-gen/src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../yanzhu-gen/src/main/resources/logback.xml | 74 + .../mapper/generator/GenTableColumnMapper.xml | 127 + .../mapper/generator/GenTableMapper.xml | 202 + .../main/resources/vm/java/controller.java.vm | 116 + .../src/main/resources/vm/java/domain.java.vm | 105 + .../src/main/resources/vm/java/mapper.java.vm | 91 + .../main/resources/vm/java/service.java.vm | 61 + .../resources/vm/java/serviceImpl.java.vm | 169 + .../main/resources/vm/java/sub-domain.java.vm | 76 + .../src/main/resources/vm/js/api.js.vm | 44 + .../src/main/resources/vm/sql/sql.vm | 22 + .../main/resources/vm/vue/index-tree.vue.vm | 474 + .../src/main/resources/vm/vue/index.vue.vm | 590 ++ .../resources/vm/vue/v3/index-tree.vue.vm | 474 + .../src/main/resources/vm/vue/v3/index.vue.vm | 590 ++ .../src/main/resources/vm/vue/v3/readme.txt | 1 + .../src/main/resources/vm/xml/mapper.xml.vm | 135 + yanzhu-modules/yanzhu-job/pom.xml | 143 + .../com/yanzhu/job/RuoYiJobApplication.java | 34 + .../com/yanzhu/job/config/ScheduleConfig.java | 57 + .../job/controller/SysJobController.java | 186 + .../job/controller/SysJobLogController.java | 92 + .../java/com/yanzhu/job/domain/SysJob.java | 171 + .../java/com/yanzhu/job/domain/SysJobLog.java | 155 + .../yanzhu/job/mapper/SysJobLogMapper.java | 64 + .../com/yanzhu/job/mapper/SysJobMapper.java | 67 + .../yanzhu/job/service/ISysJobLogService.java | 56 + .../yanzhu/job/service/ISysJobService.java | 103 + .../job/service/SysJobLogServiceImpl.java | 87 + .../yanzhu/job/service/SysJobServiceImpl.java | 261 + .../main/java/com/yanzhu/job/task/RyTask.java | 28 + .../yanzhu/job/util/AbstractQuartzJob.java | 107 + .../java/com/yanzhu/job/util/CronUtils.java | 63 + .../com/yanzhu/job/util/JobInvokeUtil.java | 182 + .../QuartzDisallowConcurrentExecution.java | 21 + .../yanzhu/job/util/QuartzJobExecution.java | 19 + .../com/yanzhu/job/util/ScheduleUtils.java | 139 + .../yanzhu-job/src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../yanzhu-job/src/main/resources/logback.xml | 74 + .../resources/mapper/job/SysJobLogMapper.xml | 93 + .../resources/mapper/job/SysJobMapper.xml | 111 + yanzhu-modules/yanzhu-manage/pom.xml | 103 + .../java/com/yanzhu/manage/controller/init | 0 .../java/com/yanzhu/manage/service/impl/init | 0 .../main/java/com/yanzhu/manage/service/init | 0 .../src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../src/main/resources/logback.xml | 74 + yanzhu-modules/yanzhu-system/pom.xml | 155 + .../yanzhu/system/RuoYiSystemApplication.java | 34 + .../system/controller/SysAreaController.java | 154 + .../controller/SysConfigController.java | 133 + .../system/controller/SysDeptController.java | 133 + .../controller/SysDictDataController.java | 122 + .../controller/SysDictTypeController.java | 132 + .../controller/SysLogininforController.java | 92 + .../system/controller/SysMenuController.java | 159 + .../controller/SysNoticeController.java | 92 + .../controller/SysOperlogController.java | 78 + .../system/controller/SysPostController.java | 130 + .../controller/SysProfileController.java | 158 + .../system/controller/SysRoleController.java | 239 + .../system/controller/SysUserController.java | 326 + .../controller/SysUserOnlineController.java | 83 + .../com/yanzhu/system/domain/SysArea.java | 97 + .../com/yanzhu/system/domain/SysConfig.java | 111 + .../com/yanzhu/system/domain/SysMenu.java | 259 + .../com/yanzhu/system/domain/SysNotice.java | 102 + .../com/yanzhu/system/domain/SysPost.java | 124 + .../com/yanzhu/system/domain/SysRoleDept.java | 46 + .../com/yanzhu/system/domain/SysRoleMenu.java | 46 + .../yanzhu/system/domain/SysUserOnline.java | 100 + .../com/yanzhu/system/domain/SysUserPost.java | 46 + .../com/yanzhu/system/domain/SysUserRole.java | 46 + .../com/yanzhu/system/domain/vo/MetaVo.java | 106 + .../com/yanzhu/system/domain/vo/RouterVo.java | 148 + .../yanzhu/system/domain/vo/TreeSelect.java | 85 + .../yanzhu/system/mapper/SysAreaMapper.java | 61 + .../yanzhu/system/mapper/SysConfigMapper.java | 76 + .../yanzhu/system/mapper/SysDeptMapper.java | 118 + .../system/mapper/SysDictDataMapper.java | 95 + .../system/mapper/SysDictTypeMapper.java | 83 + .../system/mapper/SysLogininforMapper.java | 42 + .../yanzhu/system/mapper/SysMenuMapper.java | 126 + .../yanzhu/system/mapper/SysNoticeMapper.java | 60 + .../system/mapper/SysOperLogMapper.java | 48 + .../yanzhu/system/mapper/SysPostMapper.java | 99 + .../system/mapper/SysRoleDeptMapper.java | 44 + .../yanzhu/system/mapper/SysRoleMapper.java | 107 + .../system/mapper/SysRoleMenuMapper.java | 44 + .../yanzhu/system/mapper/SysUserMapper.java | 127 + .../system/mapper/SysUserPostMapper.java | 44 + .../system/mapper/SysUserRoleMapper.java | 63 + .../system/service/ISysAreaService.java | 92 + .../system/service/ISysConfigService.java | 82 + .../system/service/ISysDeptService.java | 124 + .../system/service/ISysDictDataService.java | 60 + .../system/service/ISysDictTypeService.java | 98 + .../system/service/ISysLogininforService.java | 40 + .../system/service/ISysMenuService.java | 144 + .../system/service/ISysNoticeService.java | 60 + .../system/service/ISysOperLogService.java | 49 + .../system/service/ISysPermissionService.java | 29 + .../system/service/ISysPostService.java | 99 + .../system/service/ISysRoleService.java | 173 + .../system/service/ISysUserOnlineService.java | 48 + .../system/service/ISysUserService.java | 206 + .../service/impl/SysAreaServiceImpl.java | 221 + .../service/impl/SysConfigServiceImpl.java | 214 + .../service/impl/SysDeptServiceImpl.java | 339 + .../service/impl/SysDictDataServiceImpl.java | 112 + .../service/impl/SysDictTypeServiceImpl.java | 224 + .../impl/SysLogininforServiceImpl.java | 65 + .../service/impl/SysMenuServiceImpl.java | 532 ++ .../service/impl/SysNoticeServiceImpl.java | 93 + .../service/impl/SysOperLogServiceImpl.java | 84 + .../impl/SysPermissionServiceImpl.java | 85 + .../service/impl/SysPostServiceImpl.java | 179 + .../service/impl/SysRoleServiceImpl.java | 425 + .../impl/SysUserOnlineServiceImpl.java | 89 + .../service/impl/SysUserServiceImpl.java | 545 ++ .../src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../src/main/resources/logback.xml | 74 + .../resources/mapper/system/SysAreaMapper.xml | 68 + .../mapper/system/SysConfigMapper.xml | 117 + .../resources/mapper/system/SysDeptMapper.xml | 157 + .../mapper/system/SysDictDataMapper.xml | 124 + .../mapper/system/SysDictTypeMapper.xml | 105 + .../mapper/system/SysLogininforMapper.xml | 54 + .../resources/mapper/system/SysMenuMapper.xml | 202 + .../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 | 152 + .../mapper/system/SysRoleMenuMapper.xml | 34 + .../resources/mapper/system/SysUserMapper.xml | 221 + .../mapper/system/SysUserPostMapper.xml | 34 + .../mapper/system/SysUserRoleMapper.xml | 44 + yanzhu-modules/yanzhu-wechat/pom.xml | 154 + .../yanzhu/wechat/RuoYiWeChatApplication.java | 34 + .../java/com/yanzhu/wechat/controller/init | 0 .../java/com/yanzhu/wechat/service/impl/init | 0 .../main/java/com/yanzhu/wechat/service/init | 0 .../src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + .../src/main/resources/logback.xml | 74 + yanzhu-monitor/pom.xml | 119 + .../monitor/RuoYiMonitorApplication.java | 30 + .../monitor/config/WebSecurityConfigurer.java | 51 + yanzhu-monitor/src/main/resources/banner.txt | 10 + .../src/main/resources/bootstrap.yml | 25 + yanzhu-monitor/src/main/resources/logback.xml | 74 + yanzhu-rocketmq/pom.xml | 144 + .../yanzhu/rocketmq/RocketMQApplication.java | 27 + .../rocketmq/config/ConsumerConfig.java | 74 + .../rocketmq/config/ProducerConfig.java | 56 + .../rocketmq/consumer/RocketMsgListener.java | 86 + .../RocketMsgTransactionListenerImpl.java | 30 + .../controller/RocketMqController.java | 137 + .../rocketmq/enums/MessageCodeEnum.java | 55 + .../yanzhu/rocketmq/enums/MessageTopic.java | 24 + .../yanzhu/rocketmq/model/ConsumerMode.java | 26 + .../yanzhu/rocketmq/model/ProducerMode.java | 25 + .../rocketmq/producer/ConsumeException.java | 23 + .../rocketmq/producer/MessageProducer.java | 223 + .../src/main/resources/bootstrap.yml | 35 + .../testrocketmq/RocketMQApplication.java | 27 + .../testrocketmq/config/ConsumerConfig.java | 64 + .../testrocketmq/config/MessageConfig.java | 27 + .../testrocketmq/config/ProducerConfig.java | 48 + .../consumer/RocketMsgListener.java | 100 + .../testrocketmq/enums/MessageCodeEnum.java | 60 + .../testrocketmq/model/ConsumerMode.java | 22 + .../testrocketmq/model/ProducerMode.java | 25 + .../testrocketmq/producer/AsyncProducer.java | 47 + .../producer/ConsumeException.java | 20 + .../testrocketmq/producer/MessageContext.java | 34 + .../producer/MessageProducer.java | 110 + yanzhu-ui-app/App.vue | 28 + yanzhu-ui-app/LICENSE | 21 + yanzhu-ui-app/README.md | 52 + yanzhu-ui-app/api/callup.js | 71 + yanzhu-ui-app/api/index.js | 71 + yanzhu-ui-app/api/login.js | 50 + yanzhu-ui-app/components/navbar/Navbar.vue | 83 + yanzhu-ui-app/components/navbar/homebar.vue | 16 + yanzhu-ui-app/components/tabbar.vue | 99 + .../components/uni-section/uni-section.vue | 167 + yanzhu-ui-app/config.js | 27 + yanzhu-ui-app/main.js | 26 + yanzhu-ui-app/manifest.json | 85 + yanzhu-ui-app/package-lock.json | 24 + yanzhu-ui-app/package.json | 5 + yanzhu-ui-app/pages.json | 202 + yanzhu-ui-app/pages/centerlogin.vue | 52 + yanzhu-ui-app/pages/index.vue | 191 + yanzhu-ui-app/pages/information/end.vue | 103 + yanzhu-ui-app/pages/information/index.vue | 109 + yanzhu-ui-app/pages/information/index2.vue | 94 + yanzhu-ui-app/pages/information/index3.vue | 103 + yanzhu-ui-app/pages/information/index4.vue | 101 + yanzhu-ui-app/pages/listdeil/index.vue | 164 + yanzhu-ui-app/pages/login.vue | 372 + yanzhu-ui-app/pages/mine/index.vue | 70 + yanzhu-ui-app/pages/work/deilorder.vue | 178 + yanzhu-ui-app/pages/work/index.vue | 134 + yanzhu-ui-app/pages/workNext/index.vue | 176 + yanzhu-ui-app/pages/workNext/index2.vue | 177 + yanzhu-ui-app/pages/workNext/index3.vue | 190 + yanzhu-ui-app/pages_loader/pages/index.vue | 161 + .../pages_loader/pages/listdeil/index.vue | 80 + .../pages_loader/pages/mine/index.vue | 55 + yanzhu-ui-app/pages_loader/pages/release.vue | 190 + .../pages_loader/pages/work/deilorder.vue | 80 + .../pages_loader/pages/work/index.vue | 123 + yanzhu-ui-app/permission.js | 45 + yanzhu-ui-app/plugins/auth.js | 60 + yanzhu-ui-app/plugins/index.js | 14 + yanzhu-ui-app/plugins/modal.js | 74 + yanzhu-ui-app/plugins/tab.js | 30 + yanzhu-ui-app/project.config.json | 31 + yanzhu-ui-app/project.private.config.json | 7 + yanzhu-ui-app/static/doc.png | Bin 0 -> 1905 bytes yanzhu-ui-app/static/favicon.ico | Bin 0 -> 16958 bytes yanzhu-ui-app/static/fileimg.png | Bin 0 -> 6213 bytes yanzhu-ui-app/static/font/iconfont.ttf | Bin 0 -> 6724 bytes yanzhu-ui-app/static/images/ation.png | Bin 0 -> 12396 bytes yanzhu-ui-app/static/images/bgimg.png | Bin 0 -> 65101 bytes yanzhu-ui-app/static/images/clzgb.png | Bin 0 -> 6483 bytes yanzhu-ui-app/static/images/doudi.png | Bin 0 -> 3433 bytes yanzhu-ui-app/static/images/dsh.png | Bin 0 -> 6775 bytes yanzhu-ui-app/static/images/img1.png | Bin 0 -> 2445 bytes yanzhu-ui-app/static/images/img2.png | Bin 0 -> 2729 bytes yanzhu-ui-app/static/images/img3.png | Bin 0 -> 2543 bytes yanzhu-ui-app/static/images/img4.png | Bin 0 -> 2870 bytes yanzhu-ui-app/static/images/img5.png | Bin 0 -> 2309 bytes yanzhu-ui-app/static/images/img6.png | Bin 0 -> 2720 bytes yanzhu-ui-app/static/images/minebg.png | Bin 0 -> 7126 bytes yanzhu-ui-app/static/images/profile.jpg | Bin 0 -> 81131 bytes yanzhu-ui-app/static/images/shbh.png | Bin 0 -> 6855 bytes yanzhu-ui-app/static/images/ywc.png | Bin 0 -> 6435 bytes yanzhu-ui-app/static/index.html | 24 + yanzhu-ui-app/static/indexTJ.png | Bin 0 -> 290437 bytes yanzhu-ui-app/static/logo.png | Bin 0 -> 2102 bytes yanzhu-ui-app/static/nav.png | Bin 0 -> 7057 bytes yanzhu-ui-app/static/pdf.png | Bin 0 -> 1976 bytes yanzhu-ui-app/static/scss/global.scss | 90 + yanzhu-ui-app/static/scss/index.scss | 8 + yanzhu-ui-app/static/shujunull.png | Bin 0 -> 27254 bytes yanzhu-ui-app/static/tabarimg/fz1.png | Bin 0 -> 1166 bytes yanzhu-ui-app/static/tabarimg/fz2.png | Bin 0 -> 1568 bytes yanzhu-ui-app/static/tabarimg/fz3.png | Bin 0 -> 945 bytes yanzhu-ui-app/static/tabarimg/fz4.png | Bin 0 -> 1067 bytes yanzhu-ui-app/static/upload.png | Bin 0 -> 1340 bytes yanzhu-ui-app/static/zip.png | Bin 0 -> 1329 bytes yanzhu-ui-app/store/getters.js | 8 + yanzhu-ui-app/store/index.js | 15 + yanzhu-ui-app/store/modules/user.js | 146 + yanzhu-ui-app/uni.scss | 66 + .../uni_modules/qiun-data-charts/changelog.md | 320 + .../qiun-data-charts/qiun-data-charts.vue | 1618 ++++ .../components/qiun-error/qiun-error.vue | 46 + .../components/qiun-loading/loading1.vue | 162 + .../components/qiun-loading/loading2.vue | 170 + .../components/qiun-loading/loading3.vue | 173 + .../components/qiun-loading/loading4.vue | 222 + .../components/qiun-loading/loading5.vue | 229 + .../components/qiun-loading/qiun-loading.vue | 36 + .../js_sdk/u-charts/config-echarts.js | 422 + .../js_sdk/u-charts/config-ucharts.js | 606 ++ .../js_sdk/u-charts/readme.md | 5 + .../js_sdk/u-charts/u-charts.js | 7706 +++++++++++++++++ .../js_sdk/u-charts/u-charts.min.js | 18 + .../uni_modules/qiun-data-charts/license.md | 201 + .../uni_modules/qiun-data-charts/package.json | 80 + .../uni_modules/qiun-data-charts/readme.md | 84 + .../static/app-plus/echarts.min.js | 23 + .../qiun-data-charts/static/h5/echarts.min.js | 23 + .../uni_modules/select-lay/changelog.md | 10 + .../components/select-lay/select-lay.vue | 432 + .../uni_modules/select-lay/package.json | 80 + .../uni_modules/select-lay/readme.md | 173 + .../uni_modules/uni-badge/changelog.md | 33 + .../components/uni-badge/uni-badge.vue | 268 + .../uni_modules/uni-badge/package.json | 85 + yanzhu-ui-app/uni_modules/uni-badge/readme.md | 10 + .../uni_modules/uni-breadcrumb/changelog.md | 6 + .../uni-breadcrumb-item.vue | 121 + .../uni-breadcrumb/uni-breadcrumb.vue | 41 + .../uni_modules/uni-breadcrumb/package.json | 88 + .../uni_modules/uni-breadcrumb/readme.md | 66 + .../uni_modules/uni-calendar/changelog.md | 26 + .../components/uni-calendar/calendar.js | 546 ++ .../components/uni-calendar/i18n/en.json | 12 + .../components/uni-calendar/i18n/index.js | 8 + .../components/uni-calendar/i18n/zh-Hans.json | 12 + .../components/uni-calendar/i18n/zh-Hant.json | 12 + .../uni-calendar/uni-calendar-item.vue | 187 + .../components/uni-calendar/uni-calendar.vue | 566 ++ .../components/uni-calendar/util.js | 360 + .../uni_modules/uni-calendar/package.json | 85 + .../uni_modules/uni-calendar/readme.md | 103 + .../uni_modules/uni-card/changelog.md | 26 + .../uni-card/components/uni-card/uni-card.vue | 272 + .../uni_modules/uni-card/package.json | 90 + yanzhu-ui-app/uni_modules/uni-card/readme.md | 12 + .../uni_modules/uni-collapse/changelog.md | 36 + .../uni-collapse-item/uni-collapse-item.vue | 402 + .../components/uni-collapse/uni-collapse.vue | 147 + .../uni_modules/uni-collapse/package.json | 89 + .../uni_modules/uni-collapse/readme.md | 12 + .../uni_modules/uni-combox/changelog.md | 15 + .../components/uni-combox/uni-combox.vue | 294 + .../uni_modules/uni-combox/package.json | 90 + .../uni_modules/uni-combox/readme.md | 11 + .../uni_modules/uni-countdown/changelog.md | 24 + .../components/uni-countdown/i18n/en.json | 6 + .../components/uni-countdown/i18n/index.js | 8 + .../uni-countdown/i18n/zh-Hans.json | 6 + .../uni-countdown/i18n/zh-Hant.json | 6 + .../uni-countdown/uni-countdown.vue | 267 + .../uni_modules/uni-countdown/package.json | 86 + .../uni_modules/uni-countdown/readme.md | 10 + .../uni-data-checkbox/changelog.md | 45 + .../uni-data-checkbox/uni-data-checkbox.vue | 821 ++ .../uni-data-checkbox/package.json | 84 + .../uni_modules/uni-data-checkbox/readme.md | 18 + .../uni_modules/uni-data-picker/changelog.md | 75 + .../components/uni-data-picker/keypress.js | 45 + .../uni-data-picker/uni-data-picker.vue | 551 ++ .../uni-data-pickerview/uni-data-picker.js | 622 ++ .../uni-data-pickerview.vue | 323 + .../uni_modules/uni-data-picker/package.json | 90 + .../uni_modules/uni-data-picker/readme.md | 22 + .../uni_modules/uni-data-select/changelog.md | 35 + .../uni-data-select/uni-data-select.vue | 517 ++ .../uni_modules/uni-data-select/package.json | 85 + .../uni_modules/uni-data-select/readme.md | 8 + .../uni_modules/uni-dateformat/changelog.md | 10 + .../components/uni-dateformat/date-format.js | 200 + .../uni-dateformat/uni-dateformat.vue | 88 + .../uni_modules/uni-dateformat/package.json | 88 + .../uni_modules/uni-dateformat/readme.md | 11 + .../uni-datetime-picker/changelog.md | 133 + .../uni-datetime-picker/calendar-item.vue | 177 + .../uni-datetime-picker/calendar.vue | 928 ++ .../uni-datetime-picker/i18n/en.json | 22 + .../uni-datetime-picker/i18n/index.js | 8 + .../uni-datetime-picker/i18n/zh-Hans.json | 22 + .../uni-datetime-picker/i18n/zh-Hant.json | 22 + .../uni-datetime-picker/time-picker.vue | 934 ++ .../uni-datetime-picker.vue | 1026 +++ .../components/uni-datetime-picker/util.js | 403 + .../uni-datetime-picker/package.json | 87 + .../uni_modules/uni-datetime-picker/readme.md | 21 + .../uni_modules/uni-drawer/changelog.md | 13 + .../components/uni-drawer/keypress.js | 45 + .../components/uni-drawer/uni-drawer.vue | 183 + .../uni_modules/uni-drawer/package.json | 87 + .../uni_modules/uni-drawer/readme.md | 10 + .../uni_modules/uni-easyinput/changelog.md | 97 + .../components/uni-easyinput/common.js | 56 + .../uni-easyinput/uni-easyinput.vue | 657 ++ .../uni_modules/uni-easyinput/package.json | 87 + .../uni_modules/uni-easyinput/readme.md | 11 + .../uni_modules/uni-fab/changelog.md | 23 + .../uni-fab/components/uni-fab/uni-fab.vue | 491 ++ .../uni_modules/uni-fab/package.json | 84 + yanzhu-ui-app/uni_modules/uni-fab/readme.md | 9 + .../uni_modules/uni-fav/changelog.md | 19 + .../uni-fav/components/uni-fav/i18n/en.json | 4 + .../uni-fav/components/uni-fav/i18n/index.js | 8 + .../components/uni-fav/i18n/zh-Hans.json | 4 + .../components/uni-fav/i18n/zh-Hant.json | 4 + .../uni-fav/components/uni-fav/uni-fav.vue | 161 + .../uni_modules/uni-fav/package.json | 89 + yanzhu-ui-app/uni_modules/uni-fav/readme.md | 10 + .../uni_modules/uni-file-picker/changelog.md | 67 + .../uni-file-picker/choose-and-upload-file.js | 224 + .../uni-file-picker/uni-file-picker.vue | 667 ++ .../uni-file-picker/upload-file.vue | 325 + .../uni-file-picker/upload-image.vue | 292 + .../components/uni-file-picker/utils.js | 109 + .../uni_modules/uni-file-picker/package.json | 83 + .../uni_modules/uni-file-picker/readme.md | 11 + .../uni_modules/uni-forms/changelog.md | 92 + .../uni-forms-item/uni-forms-item.vue | 627 ++ .../components/uni-forms/uni-forms.vue | 397 + .../uni-forms/components/uni-forms/utils.js | 293 + .../components/uni-forms/validate.js | 486 ++ .../uni_modules/uni-forms/package.json | 88 + yanzhu-ui-app/uni_modules/uni-forms/readme.md | 23 + .../uni_modules/uni-goods-nav/changelog.md | 18 + .../components/uni-goods-nav/i18n/en.json | 6 + .../components/uni-goods-nav/i18n/index.js | 8 + .../uni-goods-nav/i18n/zh-Hans.json | 6 + .../uni-goods-nav/i18n/zh-Hant.json | 6 + .../uni-goods-nav/uni-goods-nav.vue | 229 + .../uni_modules/uni-goods-nav/package.json | 88 + .../uni_modules/uni-goods-nav/readme.md | 10 + .../uni_modules/uni-grid/changelog.md | 13 + .../uni-grid-item/uni-grid-item.vue | 127 + .../uni-grid/components/uni-grid/uni-grid.vue | 142 + .../uni_modules/uni-grid/package.json | 86 + yanzhu-ui-app/uni_modules/uni-grid/readme.md | 11 + .../uni_modules/uni-group/changelog.md | 16 + .../components/uni-group/uni-group.vue | 134 + .../uni_modules/uni-group/package.json | 87 + yanzhu-ui-app/uni_modules/uni-group/readme.md | 9 + .../uni_modules/uni-icons/changelog.md | 22 + .../uni-icons/components/uni-icons/icons.js | 1169 +++ .../components/uni-icons/uni-icons.vue | 96 + .../components/uni-icons/uniicons.ttf | Bin 0 -> 35760 bytes .../uni_modules/uni-icons/package.json | 86 + yanzhu-ui-app/uni_modules/uni-icons/readme.md | 8 + .../uni_modules/uni-indexed-list/changelog.md | 17 + .../uni-indexed-list-item.vue | 144 + .../uni-indexed-list/uni-indexed-list.vue | 367 + .../uni_modules/uni-indexed-list/package.json | 89 + .../uni_modules/uni-indexed-list/readme.md | 11 + .../uni_modules/uni-link/changelog.md | 17 + .../uni-link/components/uni-link/uni-link.vue | 128 + .../uni_modules/uni-link/package.json | 87 + yanzhu-ui-app/uni_modules/uni-link/readme.md | 11 + .../uni_modules/uni-list/changelog.md | 46 + .../components/uni-list-ad/uni-list-ad.vue | 107 + .../uni-list-chat/uni-list-chat.scss | 58 + .../uni-list-chat/uni-list-chat.vue | 593 ++ .../uni-list-item/uni-list-item.vue | 534 ++ .../uni-list/components/uni-list/uni-list.vue | 123 + .../components/uni-list/uni-refresh.vue | 65 + .../components/uni-list/uni-refresh.wxs | 87 + .../uni_modules/uni-list/package.json | 88 + yanzhu-ui-app/uni_modules/uni-list/readme.md | 346 + .../uni_modules/uni-load-more/changelog.md | 19 + .../components/uni-load-more/i18n/en.json | 5 + .../components/uni-load-more/i18n/index.js | 8 + .../uni-load-more/i18n/zh-Hans.json | 5 + .../uni-load-more/i18n/zh-Hant.json | 5 + .../uni-load-more/uni-load-more.vue | 399 + .../uni_modules/uni-load-more/package.json | 86 + .../uni_modules/uni-load-more/readme.md | 14 + .../uni_modules/uni-nav-bar/changelog.md | 51 + .../components/uni-nav-bar/uni-nav-bar.vue | 357 + .../components/uni-nav-bar/uni-status-bar.vue | 24 + .../uni_modules/uni-nav-bar/package.json | 86 + .../uni_modules/uni-nav-bar/readme.md | 15 + .../uni_modules/uni-notice-bar/changelog.md | 18 + .../uni-notice-bar/uni-notice-bar.vue | 426 + .../uni_modules/uni-notice-bar/package.json | 87 + .../uni_modules/uni-notice-bar/readme.md | 13 + .../uni_modules/uni-number-box/changelog.md | 25 + .../uni-number-box/uni-number-box.vue | 221 + .../uni_modules/uni-number-box/package.json | 85 + .../uni_modules/uni-number-box/readme.md | 13 + .../uni_modules/uni-pagination/changelog.md | 27 + .../components/uni-pagination/i18n/en.json | 5 + .../components/uni-pagination/i18n/es.json | 5 + .../components/uni-pagination/i18n/fr.json | 5 + .../components/uni-pagination/i18n/index.js | 12 + .../uni-pagination/i18n/zh-Hans.json | 5 + .../uni-pagination/i18n/zh-Hant.json | 5 + .../uni-pagination/uni-pagination.vue | 465 + .../uni_modules/uni-pagination/package.json | 83 + .../uni_modules/uni-pagination/readme.md | 11 + .../uni_modules/uni-popup/changelog.md | 68 + .../components/uni-popup-dialog/keypress.js | 45 + .../uni-popup-dialog/uni-popup-dialog.vue | 275 + .../uni-popup-message/uni-popup-message.vue | 143 + .../uni-popup-share/uni-popup-share.vue | 187 + .../components/uni-popup/i18n/en.json | 7 + .../components/uni-popup/i18n/index.js | 8 + .../components/uni-popup/i18n/zh-Hans.json | 7 + .../components/uni-popup/i18n/zh-Hant.json | 7 + .../components/uni-popup/keypress.js | 45 + .../uni-popup/components/uni-popup/popup.js | 26 + .../components/uni-popup/uni-popup.vue | 473 + .../uni_modules/uni-popup/package.json | 87 + yanzhu-ui-app/uni_modules/uni-popup/readme.md | 17 + .../uni_modules/uni-rate/changelog.md | 25 + .../uni-rate/components/uni-rate/uni-rate.vue | 365 + .../uni_modules/uni-rate/package.json | 88 + yanzhu-ui-app/uni_modules/uni-rate/readme.md | 12 + .../uni_modules/uni-row/changelog.md | 10 + .../uni-row/components/uni-col/uni-col.vue | 317 + .../uni-row/components/uni-row/uni-row.vue | 190 + .../uni_modules/uni-row/package.json | 87 + yanzhu-ui-app/uni_modules/uni-row/readme.md | 10 + .../uni_modules/uni-scss/changelog.md | 8 + yanzhu-ui-app/uni_modules/uni-scss/index.scss | 1 + .../uni_modules/uni-scss/package.json | 82 + yanzhu-ui-app/uni_modules/uni-scss/readme.md | 4 + .../uni_modules/uni-scss/styles/index.scss | 7 + .../uni-scss/styles/setting/_border.scss | 3 + .../uni-scss/styles/setting/_color.scss | 66 + .../uni-scss/styles/setting/_radius.scss | 55 + .../uni-scss/styles/setting/_space.scss | 56 + .../uni-scss/styles/setting/_styles.scss | 167 + .../uni-scss/styles/setting/_text.scss | 24 + .../uni-scss/styles/setting/_variables.scss | 146 + .../uni-scss/styles/tools/functions.scss | 19 + yanzhu-ui-app/uni_modules/uni-scss/theme.scss | 31 + .../uni_modules/uni-scss/variables.scss | 62 + .../uni_modules/uni-search-bar/changelog.md | 33 + .../components/uni-search-bar/i18n/en.json | 4 + .../components/uni-search-bar/i18n/index.js | 8 + .../uni-search-bar/i18n/zh-Hans.json | 4 + .../uni-search-bar/i18n/zh-Hant.json | 4 + .../uni-search-bar/uni-search-bar.vue | 298 + .../uni_modules/uni-search-bar/package.json | 89 + .../uni_modules/uni-search-bar/readme.md | 14 + .../uni-segmented-control/changelog.md | 9 + .../uni-segmented-control.vue | 145 + .../uni-segmented-control/package.json | 87 + .../uni-segmented-control/readme.md | 13 + .../uni_modules/uni-steps/changelog.md | 16 + .../components/uni-steps/uni-steps.vue | 269 + .../uni_modules/uni-steps/package.json | 89 + yanzhu-ui-app/uni_modules/uni-steps/readme.md | 13 + .../uni_modules/uni-swipe-action/changelog.md | 43 + .../uni-swipe-action-item/bindingx.js | 302 + .../components/uni-swipe-action-item/isPC.js | 12 + .../uni-swipe-action-item/mpalipay.js | 195 + .../uni-swipe-action-item/mpother.js | 260 + .../components/uni-swipe-action-item/mpwxs.js | 84 + .../uni-swipe-action-item/render.js | 270 + .../uni-swipe-action-item.vue | 347 + .../components/uni-swipe-action-item/wx.wxs | 341 + .../uni-swipe-action/uni-swipe-action.vue | 60 + .../uni_modules/uni-swipe-action/package.json | 87 + .../uni_modules/uni-swipe-action/readme.md | 11 + .../uni_modules/uni-swiper-dot/changelog.md | 12 + .../uni-swiper-dot/uni-swiper-dot.vue | 218 + .../uni_modules/uni-swiper-dot/package.json | 87 + .../uni_modules/uni-swiper-dot/readme.md | 11 + .../uni_modules/uni-table/changelog.md | 27 + .../components/uni-table/uni-table.vue | 455 + .../components/uni-tbody/uni-tbody.vue | 29 + .../uni-table/components/uni-td/uni-td.vue | 90 + .../components/uni-th/filter-dropdown.vue | 511 ++ .../uni-table/components/uni-th/uni-th.vue | 285 + .../components/uni-thead/uni-thead.vue | 129 + .../components/uni-tr/table-checkbox.vue | 179 + .../uni-table/components/uni-tr/uni-tr.vue | 171 + .../uni_modules/uni-table/i18n/en.json | 9 + .../uni_modules/uni-table/i18n/es.json | 9 + .../uni_modules/uni-table/i18n/fr.json | 9 + .../uni_modules/uni-table/i18n/index.js | 12 + .../uni_modules/uni-table/i18n/zh-Hans.json | 9 + .../uni_modules/uni-table/i18n/zh-Hant.json | 9 + .../uni_modules/uni-table/package.json | 83 + yanzhu-ui-app/uni_modules/uni-table/readme.md | 13 + .../uni_modules/uni-tag/changelog.md | 21 + .../uni-tag/components/uni-tag/uni-tag.vue | 252 + .../uni_modules/uni-tag/package.json | 87 + yanzhu-ui-app/uni_modules/uni-tag/readme.md | 13 + .../uni_modules/uni-title/changelog.md | 10 + .../components/uni-title/uni-title.vue | 171 + .../uni_modules/uni-title/package.json | 88 + yanzhu-ui-app/uni_modules/uni-title/readme.md | 14 + .../uni_modules/uni-tooltip/changelog.md | 10 + .../components/uni-tooltip/uni-tooltip.vue | 68 + .../uni_modules/uni-tooltip/package.json | 88 + .../uni_modules/uni-tooltip/readme.md | 8 + .../uni_modules/uni-transition/changelog.md | 20 + .../uni-transition/createAnimation.js | 131 + .../uni-transition/uni-transition.vue | 281 + .../uni_modules/uni-transition/package.json | 87 + .../uni_modules/uni-transition/readme.md | 11 + yanzhu-ui-app/utils/auth.js | 23 + yanzhu-ui-app/utils/common.js | 54 + yanzhu-ui-app/utils/constant.js | 9 + yanzhu-ui-app/utils/errorCode.js | 6 + yanzhu-ui-app/utils/permission.js | 51 + yanzhu-ui-app/utils/request.js | 87 + yanzhu-ui-app/utils/storage.js | 32 + yanzhu-ui-app/utils/upload.js | 70 + yanzhu-ui-app/uview-ui/LICENSE | 21 + yanzhu-ui-app/uview-ui/README.md | 66 + yanzhu-ui-app/uview-ui/changelog.md | 362 + .../uview-ui/components/u--form/u--form.vue | 78 + .../uview-ui/components/u--image/u--image.vue | 47 + .../uview-ui/components/u--input/u--input.vue | 73 + .../uview-ui/components/u--text/u--text.vue | 44 + .../components/u--textarea/u--textarea.vue | 48 + .../components/u-action-sheet/props.js | 54 + .../u-action-sheet/u-action-sheet.vue | 278 + .../uview-ui/components/u-album/props.js | 59 + .../uview-ui/components/u-album/u-album.vue | 259 + .../uview-ui/components/u-alert/props.js | 44 + .../uview-ui/components/u-alert/u-alert.vue | 243 + .../components/u-avatar-group/props.js | 52 + .../u-avatar-group/u-avatar-group.vue | 103 + .../uview-ui/components/u-avatar/props.js | 78 + .../uview-ui/components/u-avatar/u-avatar.vue | 172 + .../uview-ui/components/u-back-top/props.js | 54 + .../components/u-back-top/u-back-top.vue | 129 + .../uview-ui/components/u-badge/props.js | 72 + .../uview-ui/components/u-badge/u-badge.vue | 171 + .../uview-ui/components/u-button/nvue.scss | 46 + .../uview-ui/components/u-button/props.js | 161 + .../uview-ui/components/u-button/u-button.vue | 490 ++ .../uview-ui/components/u-button/vue.scss | 80 + .../uview-ui/components/u-calendar/header.vue | 99 + .../uview-ui/components/u-calendar/month.vue | 579 ++ .../uview-ui/components/u-calendar/props.js | 144 + .../components/u-calendar/u-calendar.vue | 384 + .../uview-ui/components/u-calendar/util.js | 85 + .../components/u-car-keyboard/props.js | 14 + .../u-car-keyboard/u-car-keyboard.vue | 311 + .../uview-ui/components/u-cell-group/props.js | 14 + .../components/u-cell-group/u-cell-group.vue | 61 + .../uview-ui/components/u-cell/props.js | 110 + .../uview-ui/components/u-cell/u-cell.vue | 229 + .../components/u-checkbox-group/props.js | 82 + .../u-checkbox-group/u-checkbox-group.vue | 103 + .../uview-ui/components/u-checkbox/props.js | 69 + .../components/u-checkbox/u-checkbox.vue | 344 + .../components/u-circle-progress/props.js | 8 + .../u-circle-progress/u-circle-progress.vue | 198 + .../uview-ui/components/u-code-input/props.js | 79 + .../components/u-code-input/u-code-input.vue | 252 + .../uview-ui/components/u-code/props.js | 34 + .../uview-ui/components/u-code/u-code.vue | 129 + .../uview-ui/components/u-col/props.js | 29 + .../uview-ui/components/u-col/u-col.vue | 162 + .../components/u-collapse-item/props.js | 59 + .../u-collapse-item/u-collapse-item.vue | 225 + .../uview-ui/components/u-collapse/props.js | 19 + .../components/u-collapse/u-collapse.vue | 90 + .../components/u-column-notice/props.js | 55 + .../u-column-notice/u-column-notice.vue | 160 + .../uview-ui/components/u-count-down/props.js | 24 + .../components/u-count-down/u-count-down.vue | 163 + .../uview-ui/components/u-count-down/utils.js | 62 + .../uview-ui/components/u-count-to/props.js | 59 + .../components/u-count-to/u-count-to.vue | 184 + .../components/u-datetime-picker/props.js | 116 + .../u-datetime-picker/u-datetime-picker.vue | 360 + .../uview-ui/components/u-divider/props.js | 44 + .../components/u-divider/u-divider.vue | 116 + .../components/u-dropdown-item/props.js | 36 + .../u-dropdown-item/u-dropdown-item.vue | 127 + .../uview-ui/components/u-dropdown/props.js | 65 + .../components/u-dropdown/u-dropdown.vue | 127 + .../uview-ui/components/u-empty/props.js | 59 + .../uview-ui/components/u-empty/u-empty.vue | 128 + .../uview-ui/components/u-form-item/props.js | 48 + .../components/u-form-item/u-form-item.vue | 235 + .../uview-ui/components/u-form/props.js | 45 + .../uview-ui/components/u-form/u-form.vue | 214 + .../uview-ui/components/u-gap/props.js | 24 + .../uview-ui/components/u-gap/u-gap.vue | 38 + .../uview-ui/components/u-grid-item/props.js | 14 + .../components/u-grid-item/u-grid-item.vue | 209 + .../uview-ui/components/u-grid/props.js | 19 + .../uview-ui/components/u-grid/u-grid.vue | 97 + .../uview-ui/components/u-icon/icons.js | 214 + .../uview-ui/components/u-icon/props.js | 89 + .../uview-ui/components/u-icon/u-icon.vue | 234 + .../uview-ui/components/u-image/props.js | 84 + .../uview-ui/components/u-image/u-image.vue | 232 + .../components/u-index-anchor/props.js | 29 + .../u-index-anchor/u-index-anchor.vue | 91 + .../uview-ui/components/u-index-item/props.js | 5 + .../components/u-index-item/u-index-item.vue | 87 + .../uview-ui/components/u-index-list/props.js | 29 + .../components/u-index-list/u-index-list.vue | 440 + .../uview-ui/components/u-input/props.js | 187 + .../uview-ui/components/u-input/u-input.vue | 354 + .../uview-ui/components/u-keyboard/props.js | 84 + .../components/u-keyboard/u-keyboard.vue | 164 + .../components/u-line-progress/props.js | 28 + .../u-line-progress/u-line-progress.vue | 144 + .../uview-ui/components/u-line/props.js | 33 + .../uview-ui/components/u-line/u-line.vue | 62 + .../uview-ui/components/u-link/props.js | 39 + .../uview-ui/components/u-link/u-link.vue | 83 + .../uview-ui/components/u-list-item/props.js | 9 + .../components/u-list-item/u-list-item.vue | 116 + .../uview-ui/components/u-list/props.js | 76 + .../uview-ui/components/u-list/u-list.vue | 157 + .../components/u-loading-icon/props.js | 59 + .../u-loading-icon/u-loading-icon.vue | 343 + .../components/u-loading-page/props.js | 49 + .../u-loading-page/u-loading-page.vue | 115 + .../uview-ui/components/u-loadmore/props.js | 94 + .../components/u-loadmore/u-loadmore.vue | 150 + .../uview-ui/components/u-modal/props.js | 84 + .../uview-ui/components/u-modal/u-modal.vue | 227 + .../uview-ui/components/u-navbar/props.js | 84 + .../uview-ui/components/u-navbar/u-navbar.vue | 186 + .../uview-ui/components/u-no-network/props.js | 19 + .../components/u-no-network/u-no-network.vue | 220 + .../uview-ui/components/u-notice-bar/props.js | 70 + .../components/u-notice-bar/u-notice-bar.vue | 101 + .../uview-ui/components/u-notify/props.js | 49 + .../uview-ui/components/u-notify/u-notify.vue | 211 + .../uview-ui/components/u-number-box/props.js | 109 + .../components/u-number-box/u-number-box.vue | 416 + .../components/u-number-keyboard/props.js | 19 + .../u-number-keyboard/u-number-keyboard.vue | 196 + .../uview-ui/components/u-overlay/props.js | 24 + .../components/u-overlay/u-overlay.vue | 68 + .../uview-ui/components/u-parse/node/node.vue | 499 ++ .../uview-ui/components/u-parse/parser.js | 1075 +++ .../uview-ui/components/u-parse/props.js | 45 + .../uview-ui/components/u-parse/u-parse.vue | 366 + .../components/u-picker-column/props.js | 5 + .../u-picker-column/u-picker-column.vue | 27 + .../uview-ui/components/u-picker/props.js | 79 + .../uview-ui/components/u-picker/u-picker.vue | 283 + .../uview-ui/components/u-popup/props.js | 79 + .../uview-ui/components/u-popup/u-popup.vue | 304 + .../components/u-radio-group/props.js | 85 + .../u-radio-group/u-radio-group.vue | 108 + .../uview-ui/components/u-radio/props.js | 64 + .../uview-ui/components/u-radio/u-radio.vue | 339 + .../uview-ui/components/u-rate/props.js | 69 + .../uview-ui/components/u-rate/u-rate.vue | 306 + .../uview-ui/components/u-read-more/props.js | 61 + .../components/u-read-more/u-read-more.vue | 157 + .../uview-ui/components/u-row-notice/props.js | 39 + .../components/u-row-notice/u-row-notice.vue | 330 + .../uview-ui/components/u-row/props.js | 19 + .../uview-ui/components/u-row/u-row.vue | 93 + .../components/u-safe-bottom/props.js | 5 + .../u-safe-bottom/u-safe-bottom.vue | 56 + .../uview-ui/components/u-scroll-list/nvue.js | 28 + .../components/u-scroll-list/other.js | 0 .../components/u-scroll-list/props.js | 34 + .../components/u-scroll-list/scrollWxs.wxs | 50 + .../u-scroll-list/u-scroll-list.vue | 224 + .../uview-ui/components/u-search/props.js | 118 + .../uview-ui/components/u-search/u-search.vue | 303 + .../uview-ui/components/u-skeleton/props.js | 59 + .../components/u-skeleton/u-skeleton.vue | 244 + .../uview-ui/components/u-slider/mpother.js | 113 + .../uview-ui/components/u-slider/mpwxs.js | 42 + .../uview-ui/components/u-slider/mpwxs.wxs | 121 + .../components/u-slider/nvue - 副本.js | 180 + .../uview-ui/components/u-slider/nvue.js | 193 + .../uview-ui/components/u-slider/props.js | 54 + .../uview-ui/components/u-slider/u-slider.vue | 55 + .../uview-ui/components/u-status-bar/props.js | 8 + .../components/u-status-bar/u-status-bar.vue | 46 + .../uview-ui/components/u-steps-item/props.js | 24 + .../components/u-steps-item/u-steps-item.vue | 316 + .../uview-ui/components/u-steps/props.js | 39 + .../uview-ui/components/u-steps/u-steps.vue | 80 + .../uview-ui/components/u-sticky/props.js | 40 + .../uview-ui/components/u-sticky/u-sticky.vue | 212 + .../uview-ui/components/u-subsection/props.js | 49 + .../components/u-subsection/u-subsection.vue | 299 + .../u-swipe-action-item/index - backup.wxs | 256 + .../components/u-swipe-action-item/index.wxs | 225 + .../u-swipe-action-item/nvue - backup.js | 270 + .../components/u-swipe-action-item/nvue.js | 174 + .../components/u-swipe-action-item/props.js | 41 + .../u-swipe-action-item.vue | 190 + .../components/u-swipe-action-item/wxs.js | 15 + .../components/u-swipe-action/props.js | 9 + .../u-swipe-action/u-swipe-action.vue | 67 + .../components/u-swiper-indicator/props.js | 29 + .../u-swiper-indicator/u-swiper-indicator.vue | 110 + .../uview-ui/components/u-swiper/props.js | 125 + .../uview-ui/components/u-swiper/u-swiper.vue | 255 + .../uview-ui/components/u-switch/props.js | 54 + .../uview-ui/components/u-switch/u-switch.vue | 177 + .../components/u-tabbar-item/props.js | 35 + .../u-tabbar-item/u-tabbar-item.vue | 142 + .../uview-ui/components/u-tabbar/props.js | 44 + .../uview-ui/components/u-tabbar/u-tabbar.vue | 141 + .../uview-ui/components/u-table/props.js | 5 + .../uview-ui/components/u-table/u-table.vue | 29 + .../uview-ui/components/u-tabs-item/props.js | 5 + .../components/u-tabs-item/u-tabs-item.vue | 29 + .../uview-ui/components/u-tabs/props.js | 64 + .../uview-ui/components/u-tabs/u-tabs.vue | 354 + .../uview-ui/components/u-tag/props.js | 84 + .../uview-ui/components/u-tag/u-tag.vue | 358 + .../uview-ui/components/u-td/props.js | 5 + .../uview-ui/components/u-td/u-td.vue | 31 + .../uview-ui/components/u-text/props.js | 110 + .../uview-ui/components/u-text/u-text.vue | 223 + .../uview-ui/components/u-text/value.js | 85 + .../uview-ui/components/u-textarea/props.js | 119 + .../components/u-textarea/u-textarea.vue | 239 + .../uview-ui/components/u-toast/u-toast.vue | 291 + .../uview-ui/components/u-toolbar/props.js | 34 + .../components/u-toolbar/u-toolbar.vue | 102 + .../components/u-tooltip/clipboard.min.js | 58 + .../uview-ui/components/u-tooltip/props.js | 59 + .../components/u-tooltip/u-tooltip.vue | 365 + .../uview-ui/components/u-tr/props.js | 5 + .../uview-ui/components/u-tr/u-tr.vue | 31 + .../components/u-transition/nvue.ani-map.js | 68 + .../uview-ui/components/u-transition/props.js | 24 + .../components/u-transition/transition.js | 157 + .../components/u-transition/u-transition.vue | 92 + .../u-transition/vue.ani-style.scss | 113 + .../uview-ui/components/u-upload/mixin.js | 21 + .../uview-ui/components/u-upload/props.js | 124 + .../uview-ui/components/u-upload/u-upload.vue | 559 ++ .../uview-ui/components/u-upload/utils.js | 151 + .../uview-ui/components/uview-ui/uview-ui.vue | 15 + yanzhu-ui-app/uview-ui/index.js | 79 + yanzhu-ui-app/uview-ui/index.scss | 23 + yanzhu-ui-app/uview-ui/libs/config/color.js | 17 + yanzhu-ui-app/uview-ui/libs/config/config.js | 34 + yanzhu-ui-app/uview-ui/libs/config/props.js | 190 + .../uview-ui/libs/config/props/actionSheet.js | 25 + .../uview-ui/libs/config/props/album.js | 25 + .../uview-ui/libs/config/props/alert.js | 22 + .../uview-ui/libs/config/props/avatar.js | 28 + .../uview-ui/libs/config/props/avatarGroup.js | 23 + .../uview-ui/libs/config/props/backtop.js | 27 + .../uview-ui/libs/config/props/badge.js | 27 + .../uview-ui/libs/config/props/button.js | 42 + .../uview-ui/libs/config/props/calendar.js | 42 + .../uview-ui/libs/config/props/carKeyboard.js | 15 + .../uview-ui/libs/config/props/cell.js | 35 + .../uview-ui/libs/config/props/cellGroup.js | 17 + .../uview-ui/libs/config/props/checkbox.js | 27 + .../libs/config/props/checkboxGroup.js | 29 + .../libs/config/props/circleProgress.js | 15 + .../uview-ui/libs/config/props/code.js | 21 + .../uview-ui/libs/config/props/codeInput.js | 29 + .../uview-ui/libs/config/props/col.js | 19 + .../uview-ui/libs/config/props/collapse.js | 17 + .../libs/config/props/collapseItem.js | 25 + .../libs/config/props/columnNotice.js | 24 + .../uview-ui/libs/config/props/countDown.js | 18 + .../uview-ui/libs/config/props/countTo.js | 25 + .../libs/config/props/datetimePicker.js | 36 + .../uview-ui/libs/config/props/divider.js | 23 + .../uview-ui/libs/config/props/empty.js | 26 + .../uview-ui/libs/config/props/form.js | 22 + .../uview-ui/libs/config/props/formItem.js | 23 + .../uview-ui/libs/config/props/gap.js | 19 + .../uview-ui/libs/config/props/grid.js | 17 + .../uview-ui/libs/config/props/gridItem.js | 16 + .../uview-ui/libs/config/props/icon.js | 36 + .../uview-ui/libs/config/props/image.js | 30 + .../uview-ui/libs/config/props/indexAnchor.js | 19 + .../uview-ui/libs/config/props/indexList.js | 19 + .../uview-ui/libs/config/props/input.js | 48 + .../uview-ui/libs/config/props/keyboard.js | 30 + .../uview-ui/libs/config/props/line.js | 20 + .../libs/config/props/lineProgress.js | 19 + .../uview-ui/libs/config/props/link.js | 26 + .../uview-ui/libs/config/props/list.js | 28 + .../uview-ui/libs/config/props/listItem.js | 15 + .../uview-ui/libs/config/props/loadingIcon.js | 30 + .../uview-ui/libs/config/props/loadingPage.js | 23 + .../uview-ui/libs/config/props/loadmore.js | 32 + .../uview-ui/libs/config/props/modal.js | 30 + .../uview-ui/libs/config/props/navbar.js | 32 + .../uview-ui/libs/config/props/noNetwork.js | 18 + .../uview-ui/libs/config/props/noticeBar.js | 27 + .../uview-ui/libs/config/props/notify.js | 22 + .../uview-ui/libs/config/props/numberBox.js | 35 + .../libs/config/props/numberKeyboard.js | 17 + .../uview-ui/libs/config/props/overlay.js | 18 + .../uview-ui/libs/config/props/parse.js | 22 + .../uview-ui/libs/config/props/picker.js | 29 + .../uview-ui/libs/config/props/popup.js | 29 + .../uview-ui/libs/config/props/radio.js | 27 + .../uview-ui/libs/config/props/radioGroup.js | 30 + .../uview-ui/libs/config/props/rate.js | 26 + .../uview-ui/libs/config/props/readMore.js | 22 + .../uview-ui/libs/config/props/row.js | 17 + .../uview-ui/libs/config/props/rowNotice.js | 21 + .../uview-ui/libs/config/props/scrollList.js | 20 + .../uview-ui/libs/config/props/search.js | 37 + .../uview-ui/libs/config/props/section.js | 24 + .../uview-ui/libs/config/props/skeleton.js | 25 + .../uview-ui/libs/config/props/slider.js | 25 + .../uview-ui/libs/config/props/statusBar.js | 15 + .../uview-ui/libs/config/props/steps.js | 21 + .../uview-ui/libs/config/props/stepsItem.js | 18 + .../uview-ui/libs/config/props/sticky.js | 20 + .../uview-ui/libs/config/props/subsection.js | 23 + .../uview-ui/libs/config/props/swipeAction.js | 15 + .../libs/config/props/swipeActionItem.js | 21 + .../uview-ui/libs/config/props/swiper.js | 39 + .../libs/config/props/swipterIndicator.js | 19 + .../uview-ui/libs/config/props/switch.js | 24 + .../uview-ui/libs/config/props/tabbar.js | 22 + .../uview-ui/libs/config/props/tabbarItem.js | 20 + .../uview-ui/libs/config/props/tabs.js | 32 + .../uview-ui/libs/config/props/tag.js | 29 + .../uview-ui/libs/config/props/text.js | 38 + .../uview-ui/libs/config/props/textarea.js | 36 + .../uview-ui/libs/config/props/toast.js | 30 + .../uview-ui/libs/config/props/toolbar.js | 21 + .../uview-ui/libs/config/props/tooltip.js | 25 + .../uview-ui/libs/config/props/transition.js | 18 + .../uview-ui/libs/config/props/upload.js | 36 + yanzhu-ui-app/uview-ui/libs/config/zIndex.js | 20 + yanzhu-ui-app/uview-ui/libs/css/color.scss | 155 + yanzhu-ui-app/uview-ui/libs/css/common.scss | 97 + .../uview-ui/libs/css/components.scss | 15 + yanzhu-ui-app/uview-ui/libs/css/flex.scss | 257 + yanzhu-ui-app/uview-ui/libs/css/h5.scss | 0 yanzhu-ui-app/uview-ui/libs/css/mixin.scss | 8 + yanzhu-ui-app/uview-ui/libs/css/mp.scss | 0 yanzhu-ui-app/uview-ui/libs/css/nvue.scss | 0 yanzhu-ui-app/uview-ui/libs/css/vue.scss | 27 + .../uview-ui/libs/function/colorGradient.js | 134 + .../uview-ui/libs/function/debounce.js | 29 + yanzhu-ui-app/uview-ui/libs/function/digit.js | 167 + yanzhu-ui-app/uview-ui/libs/function/index.js | 731 ++ .../uview-ui/libs/function/platform.js | 75 + yanzhu-ui-app/uview-ui/libs/function/test.js | 288 + .../uview-ui/libs/function/throttle.js | 30 + .../libs/luch-request/adapters/index.js | 97 + .../luch-request/core/InterceptorManager.js | 50 + .../libs/luch-request/core/Request.js | 198 + .../libs/luch-request/core/buildFullPath.js | 20 + .../libs/luch-request/core/defaults.js | 29 + .../libs/luch-request/core/dispatchRequest.js | 3 + .../libs/luch-request/core/mergeConfig.js | 103 + .../uview-ui/libs/luch-request/core/settle.js | 16 + .../libs/luch-request/helpers/buildURL.js | 69 + .../libs/luch-request/helpers/combineURLs.js | 14 + .../luch-request/helpers/isAbsoluteURL.js | 14 + .../uview-ui/libs/luch-request/index.d.ts | 116 + .../uview-ui/libs/luch-request/index.js | 3 + .../uview-ui/libs/luch-request/utils.js | 131 + .../uview-ui/libs/luch-request/utils/clone.js | 264 + yanzhu-ui-app/uview-ui/libs/mixin/button.js | 13 + yanzhu-ui-app/uview-ui/libs/mixin/mixin.js | 160 + yanzhu-ui-app/uview-ui/libs/mixin/mpMixin.js | 8 + yanzhu-ui-app/uview-ui/libs/mixin/mpShare.js | 13 + yanzhu-ui-app/uview-ui/libs/mixin/openType.js | 25 + yanzhu-ui-app/uview-ui/libs/mixin/style.js | 228 + yanzhu-ui-app/uview-ui/libs/mixin/touch.js | 59 + .../uview-ui/libs/util/async-validator.js | 1343 +++ yanzhu-ui-app/uview-ui/libs/util/calendar.js | 546 ++ yanzhu-ui-app/uview-ui/libs/util/dayjs.js | 308 + yanzhu-ui-app/uview-ui/libs/util/emitter.js | 51 + yanzhu-ui-app/uview-ui/libs/util/route.js | 124 + yanzhu-ui-app/uview-ui/package.json | 84 + yanzhu-ui-app/uview-ui/theme.scss | 44 + yanzhu-ui-vue3/.env.development | 8 + yanzhu-ui-vue3/.env.production | 11 + yanzhu-ui-vue3/.env.staging | 11 + yanzhu-ui-vue3/README.md | 143 + yanzhu-ui-vue3/bin/build.bat | 12 + yanzhu-ui-vue3/bin/package.bat | 12 + yanzhu-ui-vue3/bin/run-web.bat | 12 + yanzhu-ui-vue3/html/ie.html | 46 + yanzhu-ui-vue3/index.html | 215 + yanzhu-ui-vue3/package.json | 44 + yanzhu-ui-vue3/public/favicon.ico | Bin 0 -> 5561 bytes yanzhu-ui-vue3/src/App.vue | 21 + yanzhu-ui-vue3/src/api/login.js | 61 + yanzhu-ui-vue3/src/api/menu.js | 9 + yanzhu-ui-vue3/src/api/monitor/job.js | 71 + yanzhu-ui-vue3/src/api/monitor/jobLog.js | 26 + yanzhu-ui-vue3/src/api/monitor/online.js | 18 + yanzhu-ui-vue3/src/api/system/area.js | 68 + yanzhu-ui-vue3/src/api/system/config.js | 60 + yanzhu-ui-vue3/src/api/system/dept.js | 52 + yanzhu-ui-vue3/src/api/system/dict/data.js | 52 + yanzhu-ui-vue3/src/api/system/dict/type.js | 60 + yanzhu-ui-vue3/src/api/system/logininfor.js | 33 + yanzhu-ui-vue3/src/api/system/menu.js | 60 + yanzhu-ui-vue3/src/api/system/notice.js | 44 + yanzhu-ui-vue3/src/api/system/operlog.js | 26 + yanzhu-ui-vue3/src/api/system/post.js | 44 + yanzhu-ui-vue3/src/api/system/role.js | 119 + yanzhu-ui-vue3/src/api/system/user.js | 135 + yanzhu-ui-vue3/src/api/tool/gen.js | 76 + yanzhu-ui-vue3/src/assets/401_images/401.gif | Bin 0 -> 164227 bytes yanzhu-ui-vue3/src/assets/404_images/404.png | Bin 0 -> 98071 bytes .../src/assets/404_images/404_cloud.png | Bin 0 -> 4766 bytes yanzhu-ui-vue3/src/assets/icons/svg/404.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/bug.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/build.svg | 1 + .../src/assets/icons/svg/button.svg | 1 + .../src/assets/icons/svg/cascader.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/chart.svg | 1 + .../src/assets/icons/svg/checkbox.svg | 1 + .../src/assets/icons/svg/client.svg | 1 + .../src/assets/icons/svg/clipboard.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/code.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/color.svg | 1 + .../src/assets/icons/svg/component.svg | 1 + .../src/assets/icons/svg/dashboard.svg | 1 + .../src/assets/icons/svg/date-range.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/date.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/dict.svg | 1 + .../src/assets/icons/svg/documentation.svg | 1 + .../src/assets/icons/svg/download.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/drag.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/druid.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/edit.svg | 1 + .../src/assets/icons/svg/education.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/email.svg | 1 + .../src/assets/icons/svg/example.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/excel.svg | 1 + .../src/assets/icons/svg/exit-fullscreen.svg | 1 + .../src/assets/icons/svg/eye-open.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/eye.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/form.svg | 1 + .../src/assets/icons/svg/fullscreen.svg | 1 + .../src/assets/icons/svg/github.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/guide.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/icon.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/input.svg | 1 + .../src/assets/icons/svg/international.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/job.svg | 1 + .../src/assets/icons/svg/language.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/link.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/list.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/lock.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/log.svg | 1 + .../src/assets/icons/svg/logininfor.svg | 1 + .../src/assets/icons/svg/message.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/money.svg | 1 + .../src/assets/icons/svg/monitor.svg | 2 + yanzhu-ui-vue3/src/assets/icons/svg/nacos.svg | 1 + .../src/assets/icons/svg/nested.svg | 1 + .../src/assets/icons/svg/number.svg | 1 + .../src/assets/icons/svg/online.svg | 1 + .../src/assets/icons/svg/password.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/pdf.svg | 1 + .../src/assets/icons/svg/people.svg | 1 + .../src/assets/icons/svg/peoples.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/phone.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/post.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/qq.svg | 1 + .../src/assets/icons/svg/question.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/radio.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/rate.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/redis.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/row.svg | 1 + .../src/assets/icons/svg/search.svg | 1 + .../src/assets/icons/svg/select.svg | 1 + .../src/assets/icons/svg/sentinel.svg | 1 + .../src/assets/icons/svg/server.svg | 1 + .../src/assets/icons/svg/shopping.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/size.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/skill.svg | 1 + .../src/assets/icons/svg/slider.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/star.svg | 1 + .../src/assets/icons/svg/swagger.svg | 1 + .../src/assets/icons/svg/switch.svg | 1 + .../src/assets/icons/svg/system.svg | 2 + yanzhu-ui-vue3/src/assets/icons/svg/tab.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/table.svg | 1 + .../src/assets/icons/svg/textarea.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/theme.svg | 1 + .../src/assets/icons/svg/time-range.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/time.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/tool.svg | 1 + .../src/assets/icons/svg/tree-table.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/tree.svg | 1 + .../src/assets/icons/svg/upload.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/user.svg | 1 + .../src/assets/icons/svg/validCode.svg | 1 + .../src/assets/icons/svg/wechat.svg | 1 + yanzhu-ui-vue3/src/assets/icons/svg/zip.svg | 1 + .../src/assets/images/bg_file_v1.jpg | Bin 0 -> 391778 bytes .../src/assets/images/bg_file_v2.png | Bin 0 -> 48231 bytes .../src/assets/images/bg_file_v3.png | Bin 0 -> 5115 bytes yanzhu-ui-vue3/src/assets/images/dark.svg | 39 + yanzhu-ui-vue3/src/assets/images/light.svg | 39 + .../src/assets/images/login-background.jpg | Bin 0 -> 521275 bytes .../src/assets/images/order/order_v1.png | Bin 0 -> 54651 bytes yanzhu-ui-vue3/src/assets/images/profile.jpg | Bin 0 -> 81131 bytes yanzhu-ui-vue3/src/assets/images/task_bg.png | Bin 0 -> 54651 bytes yanzhu-ui-vue3/src/assets/logo/logo.png | Bin 0 -> 5663 bytes yanzhu-ui-vue3/src/assets/styles/btn.scss | 99 + .../src/assets/styles/element-ui.scss | 96 + yanzhu-ui-vue3/src/assets/styles/index.scss | 194 + yanzhu-ui-vue3/src/assets/styles/mixin.scss | 66 + yanzhu-ui-vue3/src/assets/styles/ruoyi.scss | 277 + yanzhu-ui-vue3/src/assets/styles/sidebar.scss | 238 + .../src/assets/styles/transition.scss | 53 + .../src/assets/styles/variables.module.scss | 65 + .../src/components/Breadcrumb/index.vue | 66 + yanzhu-ui-vue3/src/components/Crontab/day.vue | 174 + .../src/components/Crontab/hour.vue | 127 + .../src/components/Crontab/index.vue | 310 + yanzhu-ui-vue3/src/components/Crontab/min.vue | 126 + .../src/components/Crontab/month.vue | 141 + .../src/components/Crontab/result.vue | 540 ++ .../src/components/Crontab/second.vue | 128 + .../src/components/Crontab/week.vue | 197 + .../src/components/Crontab/year.vue | 149 + .../src/components/DictTag/index.vue | 49 + .../src/components/Editor/index.vue | 163 + .../src/components/FileUpload/index.vue | 205 + .../src/components/Hamburger/index.vue | 41 + .../src/components/HeaderSearch/index.vue | 179 + .../src/components/IconSelect/index.vue | 74 + .../src/components/IconSelect/requireIcons.js | 8 + .../src/components/ImagePreview/index.vue | 85 + .../src/components/ImageUpload/index.vue | 208 + .../src/components/Pagination/index.vue | 105 + .../src/components/ParentView/index.vue | 3 + .../src/components/RightToolbar/index.vue | 105 + .../src/components/RuoYi/Doc/index.vue | 13 + .../src/components/RuoYi/Git/index.vue | 13 + .../src/components/Screenfull/index.vue | 22 + .../src/components/SizeSelect/index.vue | 45 + .../src/components/SvgIcon/index.vue | 53 + .../src/components/SvgIcon/svgicon.js | 10 + .../src/components/TopNav/index.vue | 186 + .../src/components/TreeSelect/index.vue | 156 + .../src/components/iFrame/index.vue | 31 + .../src/directive/common/copyText.js | 66 + yanzhu-ui-vue3/src/directive/index.js | 9 + .../src/directive/permission/hasPermi.js | 28 + .../src/directive/permission/hasRole.js | 28 + .../src/layout/components/AppMain.vue | 53 + .../layout/components/IframeToggle/index.vue | 19 + .../src/layout/components/InnerLink/index.vue | 24 + .../src/layout/components/Navbar.vue | 191 + .../src/layout/components/Settings/index.vue | 241 + .../src/layout/components/Sidebar/Link.vue | 40 + .../src/layout/components/Sidebar/Logo.vue | 81 + .../layout/components/Sidebar/SidebarItem.vue | 102 + .../src/layout/components/Sidebar/index.vue | 54 + .../layout/components/TagsView/ScrollPane.vue | 105 + .../src/layout/components/TagsView/index.vue | 338 + yanzhu-ui-vue3/src/layout/components/index.js | 4 + yanzhu-ui-vue3/src/layout/index.vue | 111 + yanzhu-ui-vue3/src/main.js | 83 + yanzhu-ui-vue3/src/permission.js | 63 + yanzhu-ui-vue3/src/plugins/auth.js | 60 + yanzhu-ui-vue3/src/plugins/cache.js | 77 + yanzhu-ui-vue3/src/plugins/download.js | 38 + yanzhu-ui-vue3/src/plugins/index.js | 18 + yanzhu-ui-vue3/src/plugins/modal.js | 82 + yanzhu-ui-vue3/src/plugins/tab.js | 65 + yanzhu-ui-vue3/src/router/index.js | 175 + yanzhu-ui-vue3/src/settings.js | 47 + yanzhu-ui-vue3/src/store/index.js | 3 + yanzhu-ui-vue3/src/store/modules/app.js | 46 + yanzhu-ui-vue3/src/store/modules/dict.js | 57 + .../src/store/modules/permission.js | 138 + yanzhu-ui-vue3/src/store/modules/settings.js | 38 + yanzhu-ui-vue3/src/store/modules/tagsView.js | 182 + yanzhu-ui-vue3/src/store/modules/user.js | 71 + yanzhu-ui-vue3/src/utils/auth.js | 29 + yanzhu-ui-vue3/src/utils/dict.js | 24 + yanzhu-ui-vue3/src/utils/dynamicTitle.js | 15 + yanzhu-ui-vue3/src/utils/errorCode.js | 6 + yanzhu-ui-vue3/src/utils/index.js | 390 + yanzhu-ui-vue3/src/utils/jsencrypt.js | 30 + yanzhu-ui-vue3/src/utils/permission.js | 51 + yanzhu-ui-vue3/src/utils/request.js | 146 + yanzhu-ui-vue3/src/utils/ruoyi.js | 246 + yanzhu-ui-vue3/src/utils/scroll-to.js | 58 + yanzhu-ui-vue3/src/utils/theme.js | 49 + yanzhu-ui-vue3/src/utils/validate.js | 93 + yanzhu-ui-vue3/src/views/error/401.vue | 82 + yanzhu-ui-vue3/src/views/error/404.vue | 227 + yanzhu-ui-vue3/src/views/index.vue | 911 ++ yanzhu-ui-vue3/src/views/login.vue | 215 + .../src/views/monitor/job/index.vue | 483 ++ yanzhu-ui-vue3/src/views/monitor/job/log.vue | 277 + .../src/views/monitor/online/index.vue | 102 + yanzhu-ui-vue3/src/views/redirect/index.vue | 14 + yanzhu-ui-vue3/src/views/register.vue | 218 + .../src/views/system/area/index.vue | 319 + .../src/views/system/config/index.vue | 305 + .../src/views/system/dept/index.vue | 274 + yanzhu-ui-vue3/src/views/system/dict/data.vue | 350 + .../src/views/system/dict/index.vue | 312 + .../src/views/system/logininfor/index.vue | 221 + .../src/views/system/menu/index.vue | 441 + .../src/views/system/notice/index.vue | 283 + .../src/views/system/operlog/index.vue | 292 + .../src/views/system/post/index.vue | 277 + .../src/views/system/role/authUser.vue | 172 + .../src/views/system/role/index.vue | 559 ++ .../src/views/system/role/selectUser.vue | 140 + .../src/views/system/user/authRole.vue | 112 + .../src/views/system/user/index.vue | 607 ++ .../src/views/system/user/profile/index.vue | 87 + .../views/system/user/profile/resetPwd.vue | 57 + .../views/system/user/profile/userAvatar.vue | 169 + .../views/system/user/profile/userInfo.vue | 56 + yanzhu-ui-vue3/src/views/tool/build/index.vue | 3 + .../src/views/tool/gen/basicInfoForm.vue | 48 + .../src/views/tool/gen/editTable.vue | 198 + .../src/views/tool/gen/genInfoForm.vue | 281 + .../src/views/tool/gen/importTable.vue | 118 + yanzhu-ui-vue3/src/views/tool/gen/index.vue | 283 + yanzhu-ui-vue3/vite.config.js | 58 + yanzhu-ui-vue3/vite/plugins/auto-import.js | 12 + yanzhu-ui-vue3/vite/plugins/compression.js | 28 + yanzhu-ui-vue3/vite/plugins/index.js | 15 + yanzhu-ui-vue3/vite/plugins/setup-extend.js | 5 + yanzhu-ui-vue3/vite/plugins/svg-icon.js | 10 + 1472 files changed, 154644 insertions(+) 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-auth.bat create mode 100644 bin/run-gateway.bat create mode 100644 bin/run-modules-file.bat create mode 100644 bin/run-modules-gen.bat create mode 100644 bin/run-modules-job.bat create mode 100644 bin/run-modules-system.bat create mode 100644 bin/run-monitor.bat create mode 100644 docker/copy.sh create mode 100644 docker/deploy.sh create mode 100644 docker/docker-compose.yml create mode 100644 docker/mysql/db/readme.txt create mode 100644 docker/mysql/dockerfile create mode 100644 docker/nacos/conf/application.properties create mode 100644 docker/nacos/dockerfile create mode 100644 docker/nginx/conf/nginx.conf create mode 100644 docker/nginx/dockerfile create mode 100644 docker/redis/conf/redis.conf create mode 100644 docker/redis/dockerfile create mode 100644 docker/ruoyi/auth/dockerfile create mode 100644 docker/ruoyi/auth/jar/readme.txt create mode 100644 docker/ruoyi/gateway/dockerfile create mode 100644 docker/ruoyi/gateway/jar/readme.txt create mode 100644 docker/ruoyi/modules/file/dockerfile create mode 100644 docker/ruoyi/modules/file/jar/readme.txt create mode 100644 docker/ruoyi/modules/gen/dockerfile create mode 100644 docker/ruoyi/modules/gen/jar/readme.txt create mode 100644 docker/ruoyi/modules/job/dockerfile create mode 100644 docker/ruoyi/modules/job/jar/readme.txt create mode 100644 docker/ruoyi/modules/system/dockerfile create mode 100644 docker/ruoyi/modules/system/jar/readme.txt create mode 100644 docker/ruoyi/visual/monitor/dockerfile create mode 100644 docker/ruoyi/visual/monitor/jar/readme.txt create mode 100644 docsql/image.png create mode 100644 docsql/nacos配置/yz-config.sql create mode 100644 docsql/quartz.sql create mode 100644 docsql/ry-order.sql create mode 100644 docsql/ry_cloud.sql create mode 100644 docsql/分库分表/ry_seata_20210128.sql create mode 100644 docsql/分库分表/seata_account.sql create mode 100644 docsql/分库分表/seata_order.sql create mode 100644 docsql/分库分表/seata_product.sql create mode 100644 pom.xml create mode 100644 yanzhu-api/pom.xml create mode 100644 yanzhu-api/yanzhu-api-system/pom.xml create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteFileService.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteLogService.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteUserService.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDept.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictData.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictType.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysFile.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysLogininfor.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysOperLog.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysRole.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysUser.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteFileFallbackFactory.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteLogFallbackFactory.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteUserFallbackFactory.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/model/LoginUser.java create mode 100644 yanzhu-api/yanzhu-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-auth/pom.xml create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/RuoYiAuthApplication.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/controller/TokenController.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/form/LoginBody.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/form/RegisterBody.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysLoginService.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysPasswordService.java create mode 100644 yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysRecordLogService.java create mode 100644 yanzhu-auth/src/main/resources/banner.txt create mode 100644 yanzhu-auth/src/main/resources/bootstrap.yml create mode 100644 yanzhu-auth/src/main/resources/logback.xml create mode 100644 yanzhu-common/pom.xml create mode 100644 yanzhu-common/yanzhu-common-core/pom.xml create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excel.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excels.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/RateLimiter.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/CacheConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/Constants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/GenConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/HttpStatus.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ScheduleConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/SecurityConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ServiceNameConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/TokenConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/UserConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/WechatConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/modules/ManageCacheConstants.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/context/SecurityContextHolder.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/domain/R.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/IsDelEnums.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/LimitType.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/OwnerType.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/RegisterChannelEnums.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/SignUpTypeEnums.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/TaskStatus.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/UserStatus.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CaptchaException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CheckedException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/DemoModeException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/GlobalException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/InnerAuthException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/PreAuthorizeException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/ServiceException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/UtilException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotLoginException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotPermissionException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotRoleException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/base/BaseException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileNameLengthLimitExceededException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileSizeLimitExceededException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileUploadException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/InvalidExtensionException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/job/TaskException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/CaptchaExpireException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserPasswordNotMatchException.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/CharsetKit.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/Convert.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/StrFormatter.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/DateUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ExceptionUtil.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/JwtUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/NoUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/PageUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ServletUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/SpringUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/StringUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanValidators.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileTypeUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/ImageUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/MimeTypeUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/EscapeUtil.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/HTMLFilter.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpHelper.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ip/IpUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelHandlerAdapter.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelUtil.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/reflect/ReflectUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sign/Base64.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sql/SqlUtil.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/IdUtils.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/Seq.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/UUID.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/controller/BaseController.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/AjaxResult.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/BaseEntity.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/TreeEntity.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/PageDomain.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableDataInfo.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableSupport.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/Xss.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/XssValidator.java create mode 100644 yanzhu-common/yanzhu-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-common/yanzhu-common-datascope/pom.xml create mode 100644 yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/annotation/DataScope.java create mode 100644 yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/aspect/DataScopeAspect.java create mode 100644 yanzhu-common/yanzhu-common-datascope/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-common/yanzhu-common-datasource/pom.xml create mode 100644 yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Master.java create mode 100644 yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Slave.java create mode 100644 yanzhu-common/yanzhu-common-log/pom.xml create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/annotation/Log.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/aspect/LogAspect.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessStatus.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessType.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/OperatorType.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/filter/PropertyPreExcludeFilter.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/service/AsyncLogService.java create mode 100644 yanzhu-common/yanzhu-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-common/yanzhu-common-mapper/pom.xml create mode 100644 yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/mapper/domain/init create mode 100644 yanzhu-common/yanzhu-common-redis/pom.xml create mode 100644 yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/FastJson2JsonRedisSerializer.java create mode 100644 yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/RedisConfig.java create mode 100644 yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/service/RedisService.java create mode 100644 yanzhu-common/yanzhu-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-common/yanzhu-common-seata/pom.xml create mode 100644 yanzhu-common/yanzhu-common-security/pom.xml create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableCustomConfig.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableRyFeignClients.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/InnerAuth.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/Logical.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresLogin.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresPermissions.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresRoles.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/InnerAuthAspect.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/PreAuthorizeAspect.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthLogic.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthUtil.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/ApplicationConfig.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/WebMvcConfig.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignAutoConfiguration.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignRequestInterceptor.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/handler/GlobalExceptionHandler.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/interceptor/HeaderInterceptor.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/service/TokenService.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/DictUtils.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/SecurityUtils.java create mode 100644 yanzhu-common/yanzhu-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-common/yanzhu-common-swagger/pom.xml create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/annotation/EnableCustomSwagger2.java create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerAutoConfiguration.java create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerBeanPostProcessor.java create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerProperties.java create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerWebConfiguration.java create mode 100644 yanzhu-common/yanzhu-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 yanzhu-gateway/pom.xml create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/RuoYiGatewayApplication.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/CaptchaConfig.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/GatewayConfig.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/KaptchaTextCreator.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/RouterFunctionConfiguration.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/SwaggerProvider.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/CaptchaProperties.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/IgnoreWhiteProperties.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/XssProperties.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/AuthFilter.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/BlackListUrlFilter.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/CacheRequestFilter.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/ValidateCodeFilter.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/XssFilter.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/GatewayExceptionHandler.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SentinelFallbackHandler.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SwaggerHandler.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/ValidateCodeHandler.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/ValidateCodeService.java create mode 100644 yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/impl/ValidateCodeServiceImpl.java create mode 100644 yanzhu-gateway/src/main/resources/banner.txt create mode 100644 yanzhu-gateway/src/main/resources/bootstrap.yml create mode 100644 yanzhu-gateway/src/main/resources/logback.xml create mode 100644 yanzhu-modules/pom.xml create mode 100644 yanzhu-modules/yanzhu-file/pom.xml create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/RuoYiFileApplication.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/MinioConfig.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/ResourcesConfig.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/controller/SysFileController.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/FastDfsSysFileServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/ISysFileService.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/LocalSysFileServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/MinioSysFileServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/utils/FileUploadUtils.java create mode 100644 yanzhu-modules/yanzhu-file/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-file/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-file/src/main/resources/logback.xml create mode 100644 yanzhu-modules/yanzhu-gen/pom.xml create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/RuoYiGenApplication.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/config/GenConfig.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/controller/GenController.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTable.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTableColumn.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableColumnMapper.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableMapper.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableColumnServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableColumnService.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableService.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/GenUtils.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityInitializer.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityUtils.java create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/logback.xml create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableColumnMapper.xml create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableMapper.xml create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/controller.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/domain.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/mapper.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/service.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/serviceImpl.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/sub-domain.java.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/js/api.js.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/sql/sql.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index-tree.vue.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index.vue.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index.vue.vm create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/readme.txt create mode 100644 yanzhu-modules/yanzhu-gen/src/main/resources/vm/xml/mapper.xml.vm create mode 100644 yanzhu-modules/yanzhu-job/pom.xml create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/RuoYiJobApplication.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/config/ScheduleConfig.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobController.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobLogController.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJob.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJobLog.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobLogMapper.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobMapper.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobLogService.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobService.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobLogServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/task/RyTask.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/AbstractQuartzJob.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/CronUtils.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/JobInvokeUtil.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzDisallowConcurrentExecution.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzJobExecution.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/ScheduleUtils.java create mode 100644 yanzhu-modules/yanzhu-job/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-job/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-job/src/main/resources/logback.xml create mode 100644 yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobLogMapper.xml create mode 100644 yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobMapper.xml create mode 100644 yanzhu-modules/yanzhu-manage/pom.xml create mode 100644 yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/init create mode 100644 yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/init create mode 100644 yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/init create mode 100644 yanzhu-modules/yanzhu-manage/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-manage/src/main/resources/logback.xml create mode 100644 yanzhu-modules/yanzhu-system/pom.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/RuoYiSystemApplication.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysAreaController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysConfigController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDeptController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictDataController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictTypeController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysLogininforController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysMenuController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysNoticeController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysOperlogController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysPostController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysProfileController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysRoleController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserOnlineController.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysArea.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysConfig.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysMenu.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysNotice.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysPost.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleDept.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleMenu.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserOnline.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserPost.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserRole.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/MetaVo.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/RouterVo.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/TreeSelect.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysAreaMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysConfigMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDeptMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictDataMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictTypeMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysLogininforMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysMenuMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysNoticeMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysOperLogMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysPostMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleDeptMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMenuMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserPostMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserRoleMapper.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysAreaService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysConfigService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDeptService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictDataService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictTypeService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysLogininforService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysMenuService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysNoticeService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysOperLogService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPermissionService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPostService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysRoleService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserOnlineService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserService.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysAreaServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysConfigServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDeptServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictDataServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictTypeServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysLogininforServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysMenuServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysNoticeServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysOperLogServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPermissionServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPostServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysRoleServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserOnlineServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserServiceImpl.java create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/logback.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysAreaMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysConfigMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDeptMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictDataMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictTypeMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysLogininforMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysMenuMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysNoticeMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysOperLogMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysPostMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserPostMapper.xml create mode 100644 yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserRoleMapper.xml create mode 100644 yanzhu-modules/yanzhu-wechat/pom.xml create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/RuoYiWeChatApplication.java create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/controller/init create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/impl/init create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/init create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/resources/banner.txt create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/resources/bootstrap.yml create mode 100644 yanzhu-modules/yanzhu-wechat/src/main/resources/logback.xml create mode 100644 yanzhu-monitor/pom.xml create mode 100644 yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/RuoYiMonitorApplication.java create mode 100644 yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/config/WebSecurityConfigurer.java create mode 100644 yanzhu-monitor/src/main/resources/banner.txt create mode 100644 yanzhu-monitor/src/main/resources/bootstrap.yml create mode 100644 yanzhu-monitor/src/main/resources/logback.xml create mode 100644 yanzhu-rocketmq/pom.xml create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/RocketMQApplication.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ConsumerConfig.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ProducerConfig.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgListener.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgTransactionListenerImpl.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/controller/RocketMqController.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageCodeEnum.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageTopic.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ConsumerMode.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ProducerMode.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/ConsumeException.java create mode 100644 yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/MessageProducer.java create mode 100644 yanzhu-rocketmq/src/main/resources/bootstrap.yml create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/RocketMQApplication.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ConsumerConfig.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/MessageConfig.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ProducerConfig.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/consumer/RocketMsgListener.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/enums/MessageCodeEnum.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ConsumerMode.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ProducerMode.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/AsyncProducer.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/ConsumeException.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageContext.java create mode 100644 yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageProducer.java create mode 100644 yanzhu-ui-app/App.vue create mode 100644 yanzhu-ui-app/LICENSE create mode 100644 yanzhu-ui-app/README.md create mode 100644 yanzhu-ui-app/api/callup.js create mode 100644 yanzhu-ui-app/api/index.js create mode 100644 yanzhu-ui-app/api/login.js create mode 100644 yanzhu-ui-app/components/navbar/Navbar.vue create mode 100644 yanzhu-ui-app/components/navbar/homebar.vue create mode 100644 yanzhu-ui-app/components/tabbar.vue create mode 100644 yanzhu-ui-app/components/uni-section/uni-section.vue create mode 100644 yanzhu-ui-app/config.js create mode 100644 yanzhu-ui-app/main.js create mode 100644 yanzhu-ui-app/manifest.json create mode 100644 yanzhu-ui-app/package-lock.json create mode 100644 yanzhu-ui-app/package.json create mode 100644 yanzhu-ui-app/pages.json create mode 100644 yanzhu-ui-app/pages/centerlogin.vue create mode 100644 yanzhu-ui-app/pages/index.vue create mode 100644 yanzhu-ui-app/pages/information/end.vue create mode 100644 yanzhu-ui-app/pages/information/index.vue create mode 100644 yanzhu-ui-app/pages/information/index2.vue create mode 100644 yanzhu-ui-app/pages/information/index3.vue create mode 100644 yanzhu-ui-app/pages/information/index4.vue create mode 100644 yanzhu-ui-app/pages/listdeil/index.vue create mode 100644 yanzhu-ui-app/pages/login.vue create mode 100644 yanzhu-ui-app/pages/mine/index.vue create mode 100644 yanzhu-ui-app/pages/work/deilorder.vue create mode 100644 yanzhu-ui-app/pages/work/index.vue create mode 100644 yanzhu-ui-app/pages/workNext/index.vue create mode 100644 yanzhu-ui-app/pages/workNext/index2.vue create mode 100644 yanzhu-ui-app/pages/workNext/index3.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/index.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/listdeil/index.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/mine/index.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/release.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/work/deilorder.vue create mode 100644 yanzhu-ui-app/pages_loader/pages/work/index.vue create mode 100644 yanzhu-ui-app/permission.js create mode 100644 yanzhu-ui-app/plugins/auth.js create mode 100644 yanzhu-ui-app/plugins/index.js create mode 100644 yanzhu-ui-app/plugins/modal.js create mode 100644 yanzhu-ui-app/plugins/tab.js create mode 100644 yanzhu-ui-app/project.config.json create mode 100644 yanzhu-ui-app/project.private.config.json create mode 100644 yanzhu-ui-app/static/doc.png create mode 100644 yanzhu-ui-app/static/favicon.ico create mode 100644 yanzhu-ui-app/static/fileimg.png create mode 100644 yanzhu-ui-app/static/font/iconfont.ttf create mode 100644 yanzhu-ui-app/static/images/ation.png create mode 100644 yanzhu-ui-app/static/images/bgimg.png create mode 100644 yanzhu-ui-app/static/images/clzgb.png create mode 100644 yanzhu-ui-app/static/images/doudi.png create mode 100644 yanzhu-ui-app/static/images/dsh.png create mode 100644 yanzhu-ui-app/static/images/img1.png create mode 100644 yanzhu-ui-app/static/images/img2.png create mode 100644 yanzhu-ui-app/static/images/img3.png create mode 100644 yanzhu-ui-app/static/images/img4.png create mode 100644 yanzhu-ui-app/static/images/img5.png create mode 100644 yanzhu-ui-app/static/images/img6.png create mode 100644 yanzhu-ui-app/static/images/minebg.png create mode 100644 yanzhu-ui-app/static/images/profile.jpg create mode 100644 yanzhu-ui-app/static/images/shbh.png create mode 100644 yanzhu-ui-app/static/images/ywc.png create mode 100644 yanzhu-ui-app/static/index.html create mode 100644 yanzhu-ui-app/static/indexTJ.png create mode 100644 yanzhu-ui-app/static/logo.png create mode 100644 yanzhu-ui-app/static/nav.png create mode 100644 yanzhu-ui-app/static/pdf.png create mode 100644 yanzhu-ui-app/static/scss/global.scss create mode 100644 yanzhu-ui-app/static/scss/index.scss create mode 100644 yanzhu-ui-app/static/shujunull.png create mode 100644 yanzhu-ui-app/static/tabarimg/fz1.png create mode 100644 yanzhu-ui-app/static/tabarimg/fz2.png create mode 100644 yanzhu-ui-app/static/tabarimg/fz3.png create mode 100644 yanzhu-ui-app/static/tabarimg/fz4.png create mode 100644 yanzhu-ui-app/static/upload.png create mode 100644 yanzhu-ui-app/static/zip.png create mode 100644 yanzhu-ui-app/store/getters.js create mode 100644 yanzhu-ui-app/store/index.js create mode 100644 yanzhu-ui-app/store/modules/user.js create mode 100644 yanzhu-ui-app/uni.scss create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/license.md create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/package.json create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/readme.md create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/static/app-plus/echarts.min.js create mode 100644 yanzhu-ui-app/uni_modules/qiun-data-charts/static/h5/echarts.min.js create mode 100644 yanzhu-ui-app/uni_modules/select-lay/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/select-lay/components/select-lay/select-lay.vue create mode 100644 yanzhu-ui-app/uni_modules/select-lay/package.json create mode 100644 yanzhu-ui-app/uni_modules/select-lay/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-badge/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-badge/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-badge/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-breadcrumb/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-breadcrumb/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-breadcrumb/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/calendar.js create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/util.js create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-calendar/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-card/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-card/components/uni-card/uni-card.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-card/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-card/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-collapse/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-collapse/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-collapse/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-combox/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-combox/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-combox/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-countdown/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-checkbox/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-data-checkbox/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-data-checkbox/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-data-picker/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-select/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-data-select/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-data-select/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-dateformat/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js create mode 100644 yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-dateformat/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-dateformat/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-datetime-picker/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-drawer/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/keypress.js create mode 100644 yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-drawer/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-drawer/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-easyinput/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/common.js create mode 100644 yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-easyinput/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-easyinput/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-fab/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-fab/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-fab/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-fav/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-file-picker/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/utils.js create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/validate.js create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-forms/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-goods-nav/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-grid/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-grid/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-grid/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-group/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-group/components/uni-group/uni-group.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-group/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-group/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/icons.js create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-icons/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-indexed-list/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-indexed-list/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-indexed-list/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-link/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-link/components/uni-link/uni-link.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-link/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-link/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-list/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-list.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs create mode 100644 yanzhu-ui-app/uni_modules/uni-list/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-list/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-load-more/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-nav-bar/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-nav-bar/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-nav-bar/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-notice-bar/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-notice-bar/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-notice-bar/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-number-box/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-number-box/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-number-box/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-pagination/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/keypress.js create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/popup.js create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-popup/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-rate/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-rate/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-rate/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-row/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-row/components/uni-col/uni-col.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-row/components/uni-row/uni-row.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-row/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-row/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/index.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/index.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_border.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_color.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_radius.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_space.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_styles.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_text.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_variables.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/styles/tools/functions.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/theme.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-scss/variables.scss create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-search-bar/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-segmented-control/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-segmented-control/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-segmented-control/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-steps/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-steps/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-steps/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-swipe-action/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-swiper-dot/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-swiper-dot/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-swiper-dot/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-table/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-table/uni-table.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-td/uni-td.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-th/uni-th.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-thead/uni-thead.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/uni-tr.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/en.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/es.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/fr.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/index.js create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hans.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hant.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-table/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-tag/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-tag/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-tag/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-title/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-title/components/uni-title/uni-title.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-title/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-title/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-tooltip/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-tooltip/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-tooltip/readme.md create mode 100644 yanzhu-ui-app/uni_modules/uni-transition/changelog.md create mode 100644 yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/createAnimation.js create mode 100644 yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue create mode 100644 yanzhu-ui-app/uni_modules/uni-transition/package.json create mode 100644 yanzhu-ui-app/uni_modules/uni-transition/readme.md create mode 100644 yanzhu-ui-app/utils/auth.js create mode 100644 yanzhu-ui-app/utils/common.js create mode 100644 yanzhu-ui-app/utils/constant.js create mode 100644 yanzhu-ui-app/utils/errorCode.js create mode 100644 yanzhu-ui-app/utils/permission.js create mode 100644 yanzhu-ui-app/utils/request.js create mode 100644 yanzhu-ui-app/utils/storage.js create mode 100644 yanzhu-ui-app/utils/upload.js create mode 100644 yanzhu-ui-app/uview-ui/LICENSE create mode 100644 yanzhu-ui-app/uview-ui/README.md create mode 100644 yanzhu-ui-app/uview-ui/changelog.md create mode 100644 yanzhu-ui-app/uview-ui/components/u--form/u--form.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u--image/u--image.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u--input/u--input.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u--text/u--text.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u--textarea/u--textarea.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-action-sheet/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-action-sheet/u-action-sheet.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-album/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-album/u-album.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-alert/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-alert/u-alert.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-avatar-group/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-avatar-group/u-avatar-group.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-avatar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-avatar/u-avatar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-back-top/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-back-top/u-back-top.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-badge/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-badge/u-badge.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-button/nvue.scss create mode 100644 yanzhu-ui-app/uview-ui/components/u-button/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-button/u-button.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-button/vue.scss create mode 100644 yanzhu-ui-app/uview-ui/components/u-calendar/header.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-calendar/month.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-calendar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-calendar/u-calendar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-calendar/util.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-car-keyboard/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-car-keyboard/u-car-keyboard.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-cell-group/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-cell-group/u-cell-group.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-cell/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-cell/u-cell.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-checkbox-group/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-checkbox-group/u-checkbox-group.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-checkbox/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-checkbox/u-checkbox.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-circle-progress/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-circle-progress/u-circle-progress.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-code-input/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-code-input/u-code-input.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-code/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-code/u-code.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-col/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-col/u-col.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-collapse-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-collapse-item/u-collapse-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-collapse/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-collapse/u-collapse.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-column-notice/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-column-notice/u-column-notice.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-count-down/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-count-down/u-count-down.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-count-down/utils.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-count-to/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-count-to/u-count-to.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-datetime-picker/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-datetime-picker/u-datetime-picker.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-divider/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-divider/u-divider.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-dropdown-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-dropdown-item/u-dropdown-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-dropdown/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-dropdown/u-dropdown.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-empty/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-empty/u-empty.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-form-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-form-item/u-form-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-form/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-form/u-form.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-gap/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-gap/u-gap.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-grid-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-grid-item/u-grid-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-grid/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-grid/u-grid.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-icon/icons.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-icon/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-icon/u-icon.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-image/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-image/u-image.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-anchor/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-anchor/u-index-anchor.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-item/u-index-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-list/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-index-list/u-index-list.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-input/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-input/u-input.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-keyboard/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-keyboard/u-keyboard.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-line-progress/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-line-progress/u-line-progress.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-line/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-line/u-line.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-link/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-link/u-link.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-list-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-list-item/u-list-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-list/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-list/u-list.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-loading-icon/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-loading-icon/u-loading-icon.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-loading-page/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-loading-page/u-loading-page.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-loadmore/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-loadmore/u-loadmore.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-modal/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-modal/u-modal.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-navbar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-navbar/u-navbar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-no-network/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-no-network/u-no-network.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-notice-bar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-notice-bar/u-notice-bar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-notify/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-notify/u-notify.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-number-box/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-number-box/u-number-box.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-number-keyboard/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-number-keyboard/u-number-keyboard.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-overlay/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-overlay/u-overlay.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-parse/node/node.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-parse/parser.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-parse/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-parse/u-parse.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-picker-column/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-picker-column/u-picker-column.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-picker/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-picker/u-picker.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-popup/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-popup/u-popup.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-radio-group/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-radio-group/u-radio-group.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-radio/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-radio/u-radio.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-rate/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-rate/u-rate.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-read-more/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-read-more/u-read-more.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-row-notice/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-row-notice/u-row-notice.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-row/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-row/u-row.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-safe-bottom/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-safe-bottom/u-safe-bottom.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-scroll-list/nvue.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-scroll-list/other.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-scroll-list/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-scroll-list/scrollWxs.wxs create mode 100644 yanzhu-ui-app/uview-ui/components/u-scroll-list/u-scroll-list.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-search/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-search/u-search.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-skeleton/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-skeleton/u-skeleton.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/mpother.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/mpwxs.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/mpwxs.wxs create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/nvue - 副本.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/nvue.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-slider/u-slider.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-status-bar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-status-bar/u-status-bar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-steps-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-steps-item/u-steps-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-steps/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-steps/u-steps.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-sticky/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-sticky/u-sticky.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-subsection/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-subsection/u-subsection.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/index - backup.wxs create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/index.wxs create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/nvue - backup.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/nvue.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action-item/wxs.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swipe-action/u-swipe-action.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-swiper-indicator/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-swiper/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-swiper/u-swiper.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-switch/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-switch/u-switch.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabbar-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabbar-item/u-tabbar-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabbar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabbar/u-tabbar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-table/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-table/u-table.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabs-item/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabs-item/u-tabs-item.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabs/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tabs/u-tabs.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tag/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tag/u-tag.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-td/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-td/u-td.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-text/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-text/u-text.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-text/value.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-textarea/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-textarea/u-textarea.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-toast/u-toast.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-toolbar/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-toolbar/u-toolbar.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tooltip/clipboard.min.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tooltip/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tooltip/u-tooltip.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-tr/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-tr/u-tr.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-transition/nvue.ani-map.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-transition/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-transition/transition.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-transition/u-transition.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-transition/vue.ani-style.scss create mode 100644 yanzhu-ui-app/uview-ui/components/u-upload/mixin.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-upload/props.js create mode 100644 yanzhu-ui-app/uview-ui/components/u-upload/u-upload.vue create mode 100644 yanzhu-ui-app/uview-ui/components/u-upload/utils.js create mode 100644 yanzhu-ui-app/uview-ui/components/uview-ui/uview-ui.vue create mode 100644 yanzhu-ui-app/uview-ui/index.js create mode 100644 yanzhu-ui-app/uview-ui/index.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/config/color.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/config.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/actionSheet.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/album.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/alert.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/avatar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/avatarGroup.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/backtop.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/badge.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/button.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/calendar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/carKeyboard.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/cell.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/cellGroup.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/checkbox.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/checkboxGroup.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/circleProgress.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/code.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/codeInput.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/col.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/collapse.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/collapseItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/columnNotice.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/countDown.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/countTo.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/datetimePicker.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/divider.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/empty.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/form.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/formItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/gap.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/grid.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/gridItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/icon.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/image.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/indexAnchor.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/indexList.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/input.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/keyboard.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/line.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/lineProgress.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/link.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/list.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/listItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/loadingIcon.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/loadingPage.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/loadmore.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/modal.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/navbar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/noNetwork.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/noticeBar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/notify.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/numberBox.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/numberKeyboard.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/overlay.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/parse.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/picker.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/popup.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/radio.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/radioGroup.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/rate.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/readMore.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/row.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/rowNotice.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/scrollList.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/search.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/section.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/skeleton.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/slider.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/statusBar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/steps.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/stepsItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/sticky.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/subsection.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/swipeAction.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/swipeActionItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/swiper.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/swipterIndicator.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/switch.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/tabbar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/tabbarItem.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/tabs.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/tag.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/text.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/textarea.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/toast.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/toolbar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/tooltip.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/transition.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/props/upload.js create mode 100644 yanzhu-ui-app/uview-ui/libs/config/zIndex.js create mode 100644 yanzhu-ui-app/uview-ui/libs/css/color.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/common.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/components.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/flex.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/h5.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/mixin.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/mp.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/nvue.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/css/vue.scss create mode 100644 yanzhu-ui-app/uview-ui/libs/function/colorGradient.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/debounce.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/digit.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/index.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/platform.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/test.js create mode 100644 yanzhu-ui-app/uview-ui/libs/function/throttle.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/adapters/index.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/InterceptorManager.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/Request.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/buildFullPath.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/defaults.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/dispatchRequest.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/mergeConfig.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/core/settle.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/helpers/buildURL.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/helpers/combineURLs.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/index.d.ts create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/index.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/utils.js create mode 100644 yanzhu-ui-app/uview-ui/libs/luch-request/utils/clone.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/button.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/mixin.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/mpMixin.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/mpShare.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/openType.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/style.js create mode 100644 yanzhu-ui-app/uview-ui/libs/mixin/touch.js create mode 100644 yanzhu-ui-app/uview-ui/libs/util/async-validator.js create mode 100644 yanzhu-ui-app/uview-ui/libs/util/calendar.js create mode 100644 yanzhu-ui-app/uview-ui/libs/util/dayjs.js create mode 100644 yanzhu-ui-app/uview-ui/libs/util/emitter.js create mode 100644 yanzhu-ui-app/uview-ui/libs/util/route.js create mode 100644 yanzhu-ui-app/uview-ui/package.json create mode 100644 yanzhu-ui-app/uview-ui/theme.scss create mode 100644 yanzhu-ui-vue3/.env.development create mode 100644 yanzhu-ui-vue3/.env.production create mode 100644 yanzhu-ui-vue3/.env.staging create mode 100644 yanzhu-ui-vue3/README.md create mode 100644 yanzhu-ui-vue3/bin/build.bat create mode 100644 yanzhu-ui-vue3/bin/package.bat create mode 100644 yanzhu-ui-vue3/bin/run-web.bat create mode 100644 yanzhu-ui-vue3/html/ie.html create mode 100644 yanzhu-ui-vue3/index.html create mode 100644 yanzhu-ui-vue3/package.json create mode 100644 yanzhu-ui-vue3/public/favicon.ico create mode 100644 yanzhu-ui-vue3/src/App.vue create mode 100644 yanzhu-ui-vue3/src/api/login.js create mode 100644 yanzhu-ui-vue3/src/api/menu.js create mode 100644 yanzhu-ui-vue3/src/api/monitor/job.js create mode 100644 yanzhu-ui-vue3/src/api/monitor/jobLog.js create mode 100644 yanzhu-ui-vue3/src/api/monitor/online.js create mode 100644 yanzhu-ui-vue3/src/api/system/area.js create mode 100644 yanzhu-ui-vue3/src/api/system/config.js create mode 100644 yanzhu-ui-vue3/src/api/system/dept.js create mode 100644 yanzhu-ui-vue3/src/api/system/dict/data.js create mode 100644 yanzhu-ui-vue3/src/api/system/dict/type.js create mode 100644 yanzhu-ui-vue3/src/api/system/logininfor.js create mode 100644 yanzhu-ui-vue3/src/api/system/menu.js create mode 100644 yanzhu-ui-vue3/src/api/system/notice.js create mode 100644 yanzhu-ui-vue3/src/api/system/operlog.js create mode 100644 yanzhu-ui-vue3/src/api/system/post.js create mode 100644 yanzhu-ui-vue3/src/api/system/role.js create mode 100644 yanzhu-ui-vue3/src/api/system/user.js create mode 100644 yanzhu-ui-vue3/src/api/tool/gen.js create mode 100644 yanzhu-ui-vue3/src/assets/401_images/401.gif create mode 100644 yanzhu-ui-vue3/src/assets/404_images/404.png create mode 100644 yanzhu-ui-vue3/src/assets/404_images/404_cloud.png create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/404.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/bug.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/build.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/button.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/cascader.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/chart.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/checkbox.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/client.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/clipboard.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/code.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/color.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/component.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/dashboard.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/date-range.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/date.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/dict.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/documentation.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/download.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/drag.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/druid.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/edit.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/education.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/email.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/example.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/excel.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/exit-fullscreen.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/eye-open.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/eye.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/form.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/fullscreen.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/github.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/guide.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/icon.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/input.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/international.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/job.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/language.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/link.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/list.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/lock.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/log.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/logininfor.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/message.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/money.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/monitor.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/nacos.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/nested.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/number.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/online.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/password.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/pdf.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/people.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/peoples.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/phone.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/post.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/qq.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/question.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/radio.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/rate.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/redis.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/row.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/search.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/select.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/sentinel.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/server.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/shopping.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/size.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/skill.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/slider.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/star.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/swagger.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/switch.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/system.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/tab.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/table.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/textarea.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/theme.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/time-range.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/time.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/tool.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/tree-table.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/tree.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/upload.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/user.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/validCode.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/wechat.svg create mode 100644 yanzhu-ui-vue3/src/assets/icons/svg/zip.svg create mode 100644 yanzhu-ui-vue3/src/assets/images/bg_file_v1.jpg create mode 100644 yanzhu-ui-vue3/src/assets/images/bg_file_v2.png create mode 100644 yanzhu-ui-vue3/src/assets/images/bg_file_v3.png create mode 100644 yanzhu-ui-vue3/src/assets/images/dark.svg create mode 100644 yanzhu-ui-vue3/src/assets/images/light.svg create mode 100644 yanzhu-ui-vue3/src/assets/images/login-background.jpg create mode 100644 yanzhu-ui-vue3/src/assets/images/order/order_v1.png create mode 100644 yanzhu-ui-vue3/src/assets/images/profile.jpg create mode 100644 yanzhu-ui-vue3/src/assets/images/task_bg.png create mode 100644 yanzhu-ui-vue3/src/assets/logo/logo.png create mode 100644 yanzhu-ui-vue3/src/assets/styles/btn.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/element-ui.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/index.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/mixin.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/ruoyi.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/sidebar.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/transition.scss create mode 100644 yanzhu-ui-vue3/src/assets/styles/variables.module.scss create mode 100644 yanzhu-ui-vue3/src/components/Breadcrumb/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/day.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/hour.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/min.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/month.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/result.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/second.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/week.vue create mode 100644 yanzhu-ui-vue3/src/components/Crontab/year.vue create mode 100644 yanzhu-ui-vue3/src/components/DictTag/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Editor/index.vue create mode 100644 yanzhu-ui-vue3/src/components/FileUpload/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Hamburger/index.vue create mode 100644 yanzhu-ui-vue3/src/components/HeaderSearch/index.vue create mode 100644 yanzhu-ui-vue3/src/components/IconSelect/index.vue create mode 100644 yanzhu-ui-vue3/src/components/IconSelect/requireIcons.js create mode 100644 yanzhu-ui-vue3/src/components/ImagePreview/index.vue create mode 100644 yanzhu-ui-vue3/src/components/ImageUpload/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Pagination/index.vue create mode 100644 yanzhu-ui-vue3/src/components/ParentView/index.vue create mode 100644 yanzhu-ui-vue3/src/components/RightToolbar/index.vue create mode 100644 yanzhu-ui-vue3/src/components/RuoYi/Doc/index.vue create mode 100644 yanzhu-ui-vue3/src/components/RuoYi/Git/index.vue create mode 100644 yanzhu-ui-vue3/src/components/Screenfull/index.vue create mode 100644 yanzhu-ui-vue3/src/components/SizeSelect/index.vue create mode 100644 yanzhu-ui-vue3/src/components/SvgIcon/index.vue create mode 100644 yanzhu-ui-vue3/src/components/SvgIcon/svgicon.js create mode 100644 yanzhu-ui-vue3/src/components/TopNav/index.vue create mode 100644 yanzhu-ui-vue3/src/components/TreeSelect/index.vue create mode 100644 yanzhu-ui-vue3/src/components/iFrame/index.vue create mode 100644 yanzhu-ui-vue3/src/directive/common/copyText.js create mode 100644 yanzhu-ui-vue3/src/directive/index.js create mode 100644 yanzhu-ui-vue3/src/directive/permission/hasPermi.js create mode 100644 yanzhu-ui-vue3/src/directive/permission/hasRole.js create mode 100644 yanzhu-ui-vue3/src/layout/components/AppMain.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/IframeToggle/index.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/InnerLink/index.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Navbar.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Settings/index.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Sidebar/Link.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Sidebar/Logo.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Sidebar/SidebarItem.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/Sidebar/index.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/TagsView/ScrollPane.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/TagsView/index.vue create mode 100644 yanzhu-ui-vue3/src/layout/components/index.js create mode 100644 yanzhu-ui-vue3/src/layout/index.vue create mode 100644 yanzhu-ui-vue3/src/main.js create mode 100644 yanzhu-ui-vue3/src/permission.js create mode 100644 yanzhu-ui-vue3/src/plugins/auth.js create mode 100644 yanzhu-ui-vue3/src/plugins/cache.js create mode 100644 yanzhu-ui-vue3/src/plugins/download.js create mode 100644 yanzhu-ui-vue3/src/plugins/index.js create mode 100644 yanzhu-ui-vue3/src/plugins/modal.js create mode 100644 yanzhu-ui-vue3/src/plugins/tab.js create mode 100644 yanzhu-ui-vue3/src/router/index.js create mode 100644 yanzhu-ui-vue3/src/settings.js create mode 100644 yanzhu-ui-vue3/src/store/index.js create mode 100644 yanzhu-ui-vue3/src/store/modules/app.js create mode 100644 yanzhu-ui-vue3/src/store/modules/dict.js create mode 100644 yanzhu-ui-vue3/src/store/modules/permission.js create mode 100644 yanzhu-ui-vue3/src/store/modules/settings.js create mode 100644 yanzhu-ui-vue3/src/store/modules/tagsView.js create mode 100644 yanzhu-ui-vue3/src/store/modules/user.js create mode 100644 yanzhu-ui-vue3/src/utils/auth.js create mode 100644 yanzhu-ui-vue3/src/utils/dict.js create mode 100644 yanzhu-ui-vue3/src/utils/dynamicTitle.js create mode 100644 yanzhu-ui-vue3/src/utils/errorCode.js create mode 100644 yanzhu-ui-vue3/src/utils/index.js create mode 100644 yanzhu-ui-vue3/src/utils/jsencrypt.js create mode 100644 yanzhu-ui-vue3/src/utils/permission.js create mode 100644 yanzhu-ui-vue3/src/utils/request.js create mode 100644 yanzhu-ui-vue3/src/utils/ruoyi.js create mode 100644 yanzhu-ui-vue3/src/utils/scroll-to.js create mode 100644 yanzhu-ui-vue3/src/utils/theme.js create mode 100644 yanzhu-ui-vue3/src/utils/validate.js create mode 100644 yanzhu-ui-vue3/src/views/error/401.vue create mode 100644 yanzhu-ui-vue3/src/views/error/404.vue create mode 100644 yanzhu-ui-vue3/src/views/index.vue create mode 100644 yanzhu-ui-vue3/src/views/login.vue create mode 100644 yanzhu-ui-vue3/src/views/monitor/job/index.vue create mode 100644 yanzhu-ui-vue3/src/views/monitor/job/log.vue create mode 100644 yanzhu-ui-vue3/src/views/monitor/online/index.vue create mode 100644 yanzhu-ui-vue3/src/views/redirect/index.vue create mode 100644 yanzhu-ui-vue3/src/views/register.vue create mode 100644 yanzhu-ui-vue3/src/views/system/area/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/config/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/dept/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/dict/data.vue create mode 100644 yanzhu-ui-vue3/src/views/system/dict/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/logininfor/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/menu/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/notice/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/operlog/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/post/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/role/authUser.vue create mode 100644 yanzhu-ui-vue3/src/views/system/role/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/role/selectUser.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/authRole.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/profile/index.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/profile/resetPwd.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/profile/userAvatar.vue create mode 100644 yanzhu-ui-vue3/src/views/system/user/profile/userInfo.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/build/index.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/gen/basicInfoForm.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/gen/editTable.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/gen/genInfoForm.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/gen/importTable.vue create mode 100644 yanzhu-ui-vue3/src/views/tool/gen/index.vue create mode 100644 yanzhu-ui-vue3/vite.config.js create mode 100644 yanzhu-ui-vue3/vite/plugins/auto-import.js create mode 100644 yanzhu-ui-vue3/vite/plugins/compression.js create mode 100644 yanzhu-ui-vue3/vite/plugins/index.js create mode 100644 yanzhu-ui-vue3/vite/plugins/setup-extend.js create mode 100644 yanzhu-ui-vue3/vite/plugins/svg-icon.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..bd95df18 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 若依 + +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. diff --git a/README.md b/README.md new file mode 100644 index 00000000..5b71adf0 --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +

+ logo +

+

RuoYi-Cloud-RocketMQ v3.6.3

+

基于 Vue3/Element Plus/Vite 和 Spring Boot/Spring Cloud & Alibaba /RocketMQ前后端分离的分布式微服务架构

+

+ + + +

+ +## 平台简介 + +* 采用前后端分离的模式,微服务版本前端(基于优秀架构 [RuoYi-Cloud ](https://gitee.com/y_project/RuoYi-Cloud))。 +* 后端采用Spring Boot、Spring Cloud & Alibaba。 +* 注册中心、配置中心选型Nacos,权限认证使用Redis。 +* 流量控制框架选型Sentinel,分布式事务选型Seata。 +* 消息队列选型RocketMQ,多种消息发送模式。 +* 前端使用Vue3、Element Plus、Vite。 +* 提供示例模型 助力快速结合业务完成分库分表+读写分离以及分布式事务回滚 +* 一键打包Docker镜像到服务器,配置多数据源启动打包设置 +* elasticsearch搜索引擎正在集成中完成率90%,各种搜索方式助力企业快速使用 +* 0依赖可根据需求加入或剔除不使用的服务模块 +* 后续会加入更多中间件... +#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) Ant Design版本。 + +

更多扩展开发中

+ +## 系统模块 + +~~~ +com.ruoyi +├── ruoyi-ui // 前端框架 [80] +├── ruoyi-gateway // 网关模块 [8080] +├── ruoyi-auth // 认证中心 [9200] +├── ruoyi-rocketMQ // 消息队列 [9204] +├── ruoyi-manage // 分库分表 [9205] +├── ruoyi-api // 接口模块 +│ └── ruoyi-api-system // 系统接口 +├── ruoyi-common // 通用模块 +│ └── ruoyi-common-core // 核心模块 +│ └── ruoyi-common-datascope // 权限范围 +│ └── ruoyi-common-datasource // 多数据源 +│ └── ruoyi-common-log // 日志记录 +│ └── ruoyi-common-redis // 缓存服务 +│ └── ruoyi-common-seata // 分布式事务 +│ └── ruoyi-common-security // 安全模块 +│ └── ruoyi-common-swagger // 系统接口 +├── ruoyi-modules // 业务模块 +│ └── ruoyi-system // 系统模块 [9201] +│ └── ruoyi-gen // 代码生成 [9202] +│ └── ruoyi-job // 定时任务 [9203] +│ └── ruoyi-file // 文件服务 [9300] +├── ruoyi-visual // 图形化管理模块 +│ └── ruoyi-visual-monitor // 监控中心 [9100] +├──pom.xml // 公共依赖 +~~~ + +由个人原因没有时间写文档 有不明白的地方朋友请加好友 + + + +目前2023.11.14更新rocketMq发送消息类型: + +1.同步发送:通过调用 send() 方法发送消息,阻塞等待服务器响应。 + +2.异步发送:通过调用 send() 方法,并传入一个 SendCallback 对象,在发送消息的同时可以继续处理其他逻辑,消息发送结果通过回调函数通知。 + +3.单向发送:通过调用 sendOneway() 方法发送消息,不关心发送结果,适用于对可靠性要求不高的场景。 + +4.顺序发送:通过设置 List数据和定义 messageQueueNumber消息队列数量来保证消息按顺序发送。 + +5.延迟发送:通过设置延迟级别来实现延迟发送消息。 + +6.批量发送:通过调用 send() 方法并传入多条消息,实现批量发送消息。 + +7.事务消息发送:通过使用事务监听器实现本地事务执行和消息发送的一致性。 + +## 架构图 + + + +## 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 通知公告:系统通知公告信息发布维护。 +9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +10. 登录日志:系统登录日志记录查询包含登录异常。 +11. 在线用户:当前系统中活跃用户状态监控。 +12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 +13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 +14. 系统接口:根据业务代码自动生成相关的api接口文档。 +15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 +16. 在线构建器:拖动表单元素生成相应的HTML代码。 +17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 + +## 演示图 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/bin/clean.bat b/bin/clean.bat new file mode 100644 index 00000000..24c09741 --- /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 00000000..c693ec06 --- /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-auth.bat b/bin/run-auth.bat new file mode 100644 index 00000000..0d0952af --- /dev/null +++ b/bin/run-auth.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarAuth̡ +echo. + +cd %~dp0 +cd ../ruoyi-auth/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-auth.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-gateway.bat b/bin/run-gateway.bat new file mode 100644 index 00000000..e43d60bc --- /dev/null +++ b/bin/run-gateway.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarGateway̡ +echo. + +cd %~dp0 +cd ../ruoyi-gateway/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-gateway.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-modules-file.bat b/bin/run-modules-file.bat new file mode 100644 index 00000000..6d89c905 --- /dev/null +++ b/bin/run-modules-file.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarModules-File̡ +echo. + +cd %~dp0 +cd ../ruoyi-modules/ruoyi-file/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-file.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-modules-gen.bat b/bin/run-modules-gen.bat new file mode 100644 index 00000000..0a4c3905 --- /dev/null +++ b/bin/run-modules-gen.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarModules-Gen̡ +echo. + +cd %~dp0 +cd ../ruoyi-modules/ruoyi-gen/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-gen.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-modules-job.bat b/bin/run-modules-job.bat new file mode 100644 index 00000000..443e59d0 --- /dev/null +++ b/bin/run-modules-job.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarModules-Job̡ +echo. + +cd %~dp0 +cd ../ruoyi-modules/ruoyi-job/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-job.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-modules-system.bat b/bin/run-modules-system.bat new file mode 100644 index 00000000..26db55e4 --- /dev/null +++ b/bin/run-modules-system.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarModules-System̡ +echo. + +cd %~dp0 +cd ../ruoyi-modules/ruoyi-system/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-system.jar + +cd bin +pause \ No newline at end of file diff --git a/bin/run-monitor.bat b/bin/run-monitor.bat new file mode 100644 index 00000000..3e8e322b --- /dev/null +++ b/bin/run-monitor.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarMonitor̡ +echo. + +cd %~dp0 +cd ../ruoyi-visual/ruoyi-monitor/target + +set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-visual-monitor.jar + +cd bin +pause \ No newline at end of file diff --git a/docker/copy.sh b/docker/copy.sh new file mode 100644 index 00000000..ec2915b8 --- /dev/null +++ b/docker/copy.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# 复制项目的文件到对应docker路径,便于一键生成镜像。 +usage() { + echo "Usage: sh copy.sh" + exit 1 +} + + +# copy sql +echo "begin copy sql " +cp ../sql/ry_20220814.sql ./mysql/db +cp ../sql/ry_config_20220510.sql ./mysql/db + +# copy html +echo "begin copy html " +cp -r ../ruoyi-ui/dist/** ./nginx/html/dist + + +# copy jar +echo "begin copy ruoyi-gateway " +cp ../ruoyi-gateway/target/ruoyi-gateway.jar ./ruoyi/gateway/jar + +echo "begin copy ruoyi-auth " +cp ../ruoyi-auth/target/ruoyi-auth.jar ./ruoyi/auth/jar + +echo "begin copy ruoyi-visual " +cp ../ruoyi-visual/ruoyi-monitor/target/ruoyi-visual-monitor.jar ./ruoyi/visual/monitor/jar + +echo "begin copy ruoyi-modules-system " +cp ../ruoyi-modules/ruoyi-system/target/ruoyi-modules-system.jar ./ruoyi/modules/system/jar + +echo "begin copy ruoyi-modules-file " +cp ../ruoyi-modules/ruoyi-file/target/ruoyi-modules-file.jar ./ruoyi/modules/file/jar + +echo "begin copy ruoyi-modules-job " +cp ../ruoyi-modules/ruoyi-job/target/ruoyi-modules-job.jar ./ruoyi/modules/job/jar + +echo "begin copy ruoyi-modules-gen " +cp ../ruoyi-modules/ruoyi-gen/target/ruoyi-modules-gen.jar ./ruoyi/modules/gen/jar + diff --git a/docker/deploy.sh b/docker/deploy.sh new file mode 100644 index 00000000..02489092 --- /dev/null +++ b/docker/deploy.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# 使用说明,用来提示输入参数 +usage() { + echo "Usage: sh 执行脚本.sh [port|base|modules|stop|rm]" + exit 1 +} + +# 开启所需端口 +port(){ + firewall-cmd --add-port=80/tcp --permanent + firewall-cmd --add-port=8080/tcp --permanent + firewall-cmd --add-port=8848/tcp --permanent + firewall-cmd --add-port=9848/tcp --permanent + firewall-cmd --add-port=9849/tcp --permanent + firewall-cmd --add-port=6379/tcp --permanent + firewall-cmd --add-port=3306/tcp --permanent + firewall-cmd --add-port=9100/tcp --permanent + firewall-cmd --add-port=9200/tcp --permanent + firewall-cmd --add-port=9201/tcp --permanent + firewall-cmd --add-port=9202/tcp --permanent + firewall-cmd --add-port=9203/tcp --permanent + firewall-cmd --add-port=9300/tcp --permanent + service firewalld restart +} + +# 启动基础环境(必须) +base(){ + docker-compose up -d ruoyi-mysql ruoyi-redis ruoyi-nacos +} + +# 启动程序模块(必须) +modules(){ + docker-compose up -d ruoyi-nginx ruoyi-gateway ruoyi-auth ruoyi-modules-system +} + +# 关闭所有环境/模块 +stop(){ + docker-compose stop +} + +# 删除所有环境/模块 +rm(){ + docker-compose rm +} + +# 根据输入参数,选择执行对应方法,不输入则执行使用说明 +case "$1" in +"port") + port +;; +"base") + base +;; +"modules") + modules +;; +"stop") + stop +;; +"rm") + rm +;; +*) + usage +;; +esac diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..931249d6 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,140 @@ +version : '3.8' +services: + ruoyi-nacos: + container_name: ruoyi-nacos + image: nacos/nacos-server + build: + context: ./nacos + environment: + - MODE=standalone + volumes: + - ./nacos/logs/:/home/nacos/logs + - ./nacos/conf/application.properties:/home/nacos/conf/application.properties + ports: + - "8848:8848" + - "9848:9848" + - "9849:9849" + depends_on: + - ruoyi-mysql + ruoyi-mysql: + container_name: ruoyi-mysql + image: mysql:5.7 + build: + context: ./mysql + ports: + - "3306:3306" + volumes: + - ./mysql/conf:/etc/mysql/conf.d + - ./mysql/logs:/logs + - ./mysql/data:/var/lib/mysql + command: [ + 'mysqld', + '--innodb-buffer-pool-size=80M', + '--character-set-server=utf8mb4', + '--collation-server=utf8mb4_unicode_ci', + '--default-time-zone=+8:00', + '--lower-case-table-names=1' + ] + environment: + MYSQL_DATABASE: 'ry-cloud' + MYSQL_ROOT_PASSWORD: password + ruoyi-redis: + container_name: ruoyi-redis + image: redis + build: + context: ./redis + ports: + - "6379:6379" + volumes: + - ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf + - ./redis/data:/data + command: redis-server /home/ruoyi/redis/redis.conf + ruoyi-nginx: + container_name: ruoyi-nginx + image: nginx + build: + context: ./nginx + ports: + - "80:80" + volumes: + - ./nginx/html/dist:/home/ruoyi/projects/ruoyi-ui + - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf + - ./nginx/logs:/var/log/nginx + - ./nginx/conf.d:/etc/nginx/conf.d + depends_on: + - ruoyi-gateway + links: + - ruoyi-gateway + ruoyi-gateway: + container_name: ruoyi-gateway + build: + context: ./ruoyi/gateway + dockerfile: dockerfile + ports: + - "8080:8080" + depends_on: + - ruoyi-redis + links: + - ruoyi-redis + ruoyi-auth: + container_name: ruoyi-auth + build: + context: ./ruoyi/auth + dockerfile: dockerfile + ports: + - "9200:9200" + depends_on: + - ruoyi-redis + links: + - ruoyi-redis + ruoyi-modules-system: + container_name: ruoyi-modules-system + build: + context: ./ruoyi/modules/system + dockerfile: dockerfile + ports: + - "9201:9201" + depends_on: + - ruoyi-redis + - ruoyi-mysql + links: + - ruoyi-redis + - ruoyi-mysql + ruoyi-modules-gen: + container_name: ruoyi-modules-gen + build: + context: ./ruoyi/modules/gen + dockerfile: dockerfile + ports: + - "9202:9202" + depends_on: + - ruoyi-mysql + links: + - ruoyi-mysql + ruoyi-modules-job: + container_name: ruoyi-modules-job + build: + context: ./ruoyi/modules/job + dockerfile: dockerfile + ports: + - "9203:9203" + depends_on: + - ruoyi-mysql + links: + - ruoyi-mysql + ruoyi-modules-file: + container_name: ruoyi-modules-file + build: + context: ./ruoyi/modules/file + dockerfile: dockerfile + ports: + - "9300:9300" + volumes: + - ./ruoyi/uploadPath:/home/ruoyi/uploadPath + ruoyi-visual-monitor: + container_name: ruoyi-visual-monitor + build: + context: ./ruoyi/visual/monitor + dockerfile: dockerfile + ports: + - "9100:9100" diff --git a/docker/mysql/db/readme.txt b/docker/mysql/db/readme.txt new file mode 100644 index 00000000..0b22f3fe --- /dev/null +++ b/docker/mysql/db/readme.txt @@ -0,0 +1 @@ +sqlĿ¼µнűdockerԶִС \ No newline at end of file diff --git a/docker/mysql/dockerfile b/docker/mysql/dockerfile new file mode 100644 index 00000000..cc006f40 --- /dev/null +++ b/docker/mysql/dockerfile @@ -0,0 +1,7 @@ +# 基础镜像 +FROM mysql:5.7 +# author +MAINTAINER ruoyi + +# 执行sql脚本 +ADD ./db/*.sql /docker-entrypoint-initdb.d/ diff --git a/docker/nacos/conf/application.properties b/docker/nacos/conf/application.properties new file mode 100644 index 00000000..7f2a61f2 --- /dev/null +++ b/docker/nacos/conf/application.properties @@ -0,0 +1,32 @@ +spring.datasource.platform=mysql +db.num=1 +db.url.0=jdbc:mysql://ruoyi-mysql:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC +db.user=root +db.password=password + +nacos.naming.empty-service.auto-clean=true +nacos.naming.empty-service.clean.initial-delay-ms=50000 +nacos.naming.empty-service.clean.period-time-ms=30000 + +management.endpoints.web.exposure.include=* + +management.metrics.export.elastic.enabled=false +management.metrics.export.influx.enabled=false + +server.tomcat.accesslog.enabled=true +server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i + +server.tomcat.basedir=/home/ruoyi/nacos/tomcat/logs + +nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/** + +nacos.core.auth.system.type=nacos +nacos.core.auth.enabled=false +nacos.core.auth.default.token.expire.seconds=18000 +nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 +nacos.core.auth.caching.enabled=true +nacos.core.auth.enable.userAgentAuthWhite=false +nacos.core.auth.server.identity.key=serverIdentity +nacos.core.auth.server.identity.value=security + +nacos.istio.mcp.server.enabled=false diff --git a/docker/nacos/dockerfile b/docker/nacos/dockerfile new file mode 100644 index 00000000..b74762cc --- /dev/null +++ b/docker/nacos/dockerfile @@ -0,0 +1,7 @@ +# 基础镜像 +FROM nacos/nacos-server +# author +MAINTAINER ruoyi + +# 复制conf文件到路径 +COPY ./conf/application.properties /home/nacos/conf/application.properties diff --git a/docker/nginx/conf/nginx.conf b/docker/nginx/conf/nginx.conf new file mode 100644 index 00000000..625603bc --- /dev/null +++ b/docker/nginx/conf/nginx.conf @@ -0,0 +1,36 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + server_name localhost; + + location / { + root /home/ruoyi/projects/ruoyi-ui; + try_files $uri $uri/ /index.html; + index index.html index.htm; + } + + location /prod-api/{ + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header REMOTE-HOST $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://ruoyi-gateway:8080/; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + } +}# requirepass 123456 \ No newline at end of file diff --git a/docker/nginx/dockerfile b/docker/nginx/dockerfile new file mode 100644 index 00000000..53b136de --- /dev/null +++ b/docker/nginx/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM nginx +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi/projects/ruoyi-ui +# 创建目录 +RUN mkdir -p /home/ruoyi/projects/ruoyi-ui +# 指定路径 +WORKDIR /home/ruoyi/projects/ruoyi-ui +# 复制conf文件到路径 +COPY ./conf/nginx.conf /etc/nginx/nginx.conf +# 复制html文件到路径 +COPY ./html/dist /home/ruoyi/projects/ruoyi-ui diff --git a/docker/redis/conf/redis.conf b/docker/redis/conf/redis.conf new file mode 100644 index 00000000..d762d650 --- /dev/null +++ b/docker/redis/conf/redis.conf @@ -0,0 +1 @@ +# requirepass 123456 \ No newline at end of file diff --git a/docker/redis/dockerfile b/docker/redis/dockerfile new file mode 100644 index 00000000..05c2bc4a --- /dev/null +++ b/docker/redis/dockerfile @@ -0,0 +1,13 @@ +# 基础镜像 +FROM redis +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi/redis +# 创建目录 +RUN mkdir -p /home/ruoyi/redis +# 指定路径 +WORKDIR /home/ruoyi/redis +# 复制conf文件到路径 +COPY ./conf/redis.conf /home/ruoyi/redis/redis.conf diff --git a/docker/ruoyi/auth/dockerfile b/docker/ruoyi/auth/dockerfile new file mode 100644 index 00000000..f3c87c54 --- /dev/null +++ b/docker/ruoyi/auth/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-auth.jar /home/ruoyi/ruoyi-auth.jar +# 启动认证服务 +ENTRYPOINT ["java","-jar","ruoyi-auth.jar"] \ No newline at end of file diff --git a/docker/ruoyi/auth/jar/readme.txt b/docker/ruoyi/auth/jar/readme.txt new file mode 100644 index 00000000..c35ba276 --- /dev/null +++ b/docker/ruoyi/auth/jar/readme.txt @@ -0,0 +1 @@ +֤ĴõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/gateway/dockerfile b/docker/ruoyi/gateway/dockerfile new file mode 100644 index 00000000..0e8f612e --- /dev/null +++ b/docker/ruoyi/gateway/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-gateway.jar /home/ruoyi/ruoyi-gateway.jar +# 启动网关服务 +ENTRYPOINT ["java","-jar","ruoyi-gateway.jar"] \ No newline at end of file diff --git a/docker/ruoyi/gateway/jar/readme.txt b/docker/ruoyi/gateway/jar/readme.txt new file mode 100644 index 00000000..5dfbec76 --- /dev/null +++ b/docker/ruoyi/gateway/jar/readme.txt @@ -0,0 +1 @@ +ģõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/modules/file/dockerfile b/docker/ruoyi/modules/file/dockerfile new file mode 100644 index 00000000..3e23c935 --- /dev/null +++ b/docker/ruoyi/modules/file/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-modules-file.jar /home/ruoyi/ruoyi-modules-file.jar +# 启动文件服务 +ENTRYPOINT ["java","-jar","ruoyi-modules-file.jar"] \ No newline at end of file diff --git a/docker/ruoyi/modules/file/jar/readme.txt b/docker/ruoyi/modules/file/jar/readme.txt new file mode 100644 index 00000000..bf2b2a7f --- /dev/null +++ b/docker/ruoyi/modules/file/jar/readme.txt @@ -0,0 +1 @@ +ļõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/modules/gen/dockerfile b/docker/ruoyi/modules/gen/dockerfile new file mode 100644 index 00000000..4da8f302 --- /dev/null +++ b/docker/ruoyi/modules/gen/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-modules-gen.jar /home/ruoyi/ruoyi-modules-gen.jar +# 启动代码生成服务 +ENTRYPOINT ["java","-jar","ruoyi-modules-gen.jar"] \ No newline at end of file diff --git a/docker/ruoyi/modules/gen/jar/readme.txt b/docker/ruoyi/modules/gen/jar/readme.txt new file mode 100644 index 00000000..2f25c0af --- /dev/null +++ b/docker/ruoyi/modules/gen/jar/readme.txt @@ -0,0 +1 @@ +ŴɴõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/modules/job/dockerfile b/docker/ruoyi/modules/job/dockerfile new file mode 100644 index 00000000..3c4f7c7e --- /dev/null +++ b/docker/ruoyi/modules/job/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-modules-job.jar /home/ruoyi/ruoyi-modules-job.jar +# 启动定时任务服务 +ENTRYPOINT ["java","-jar","ruoyi-modules-job.jar"] \ No newline at end of file diff --git a/docker/ruoyi/modules/job/jar/readme.txt b/docker/ruoyi/modules/job/jar/readme.txt new file mode 100644 index 00000000..58aea0b1 --- /dev/null +++ b/docker/ruoyi/modules/job/jar/readme.txt @@ -0,0 +1 @@ +ŶʱõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/modules/system/dockerfile b/docker/ruoyi/modules/system/dockerfile new file mode 100644 index 00000000..fd825ecc --- /dev/null +++ b/docker/ruoyi/modules/system/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-modules-system.jar /home/ruoyi/ruoyi-modules-system.jar +# 启动系统服务 +ENTRYPOINT ["java","-jar","ruoyi-modules-system.jar"] \ No newline at end of file diff --git a/docker/ruoyi/modules/system/jar/readme.txt b/docker/ruoyi/modules/system/jar/readme.txt new file mode 100644 index 00000000..cfc2a927 --- /dev/null +++ b/docker/ruoyi/modules/system/jar/readme.txt @@ -0,0 +1 @@ +ϵͳģõjarļdockerӦá \ No newline at end of file diff --git a/docker/ruoyi/visual/monitor/dockerfile b/docker/ruoyi/visual/monitor/dockerfile new file mode 100644 index 00000000..1f171823 --- /dev/null +++ b/docker/ruoyi/visual/monitor/dockerfile @@ -0,0 +1,15 @@ +# 基础镜像 +FROM openjdk:8-jre +# author +MAINTAINER ruoyi + +# 挂载目录 +VOLUME /home/ruoyi +# 创建目录 +RUN mkdir -p /home/ruoyi +# 指定路径 +WORKDIR /home/ruoyi +# 复制jar文件到路径 +COPY ./jar/ruoyi-visual-monitor.jar /home/ruoyi/ruoyi-visual-monitor.jar +# 启动系统服务 +ENTRYPOINT ["java","-jar","ruoyi-visual-monitor.jar"] \ No newline at end of file diff --git a/docker/ruoyi/visual/monitor/jar/readme.txt b/docker/ruoyi/visual/monitor/jar/readme.txt new file mode 100644 index 00000000..62b28410 --- /dev/null +++ b/docker/ruoyi/visual/monitor/jar/readme.txt @@ -0,0 +1 @@ +żĴõjarļdockerӦá \ No newline at end of file diff --git a/docsql/image.png b/docsql/image.png new file mode 100644 index 0000000000000000000000000000000000000000..93bd8863d162f63d3b219a3d92867ac1bbdaf8be GIT binary patch literal 1031521 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

LH!A9xU2zLlPQDJz^b>41P(X@U`x^Y! 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�Cm1xD< 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�jyuw9^d3_(*N8bvtr9^exMKEuX7$Jh$vt~!e zV>XA>E}wx}GPT+?0_ejTTh{e*kzp^`f_1+IJXi0cJ`_gZX#^S_V$U(Q9G=V}N+pPA zb8RtMDjj0`+k04xhp-XwiTqdcKSdm@T}Qq^=j#v_jNQ|~w={d<{8;{IK8GjWop{;Z zh9}7|mS6p>&aa#RlASUq&LWAXqM@NoT*xiA4L-(NL8 z$IsJ?_=Hd~soz>8){MZDy=NVp;1@_i11@;@jZTrthf`{R!~`3!t0(syybrN4kGj74UlEtvwqh6n$!7{ zd0hMfn|Xg`4zcz4IVQUMFx8pFbTWbI_Aq9W1g;6=~-jIGJsD!^s! zZ5ZR7?>Awb$vSt2}37+N4ZN?8Z6a;CW>~IM=QC+I)|vNybi& zYqcXh9g5?5uNQB6ym;H=2D57EfIQqE#&BO$ngHBBHIORz@5SK!qce=O-kmGHq`{I@F9!pIPU5MI^_&u4beuNp!ZrbO2T<@^9Ue z33BS$kuucm0Tz8xq^%y593JGF zn`H7&v!#y#wwoS1O3z=Y0TCT~Ynp6^8tJ=tB+`Wu zKWqe{DoZBQ`g@>O>u7h~m%v7;HknQWQ~|IeSym}CzfVD|M(mjNt(5%gLV~ik%H(RT zF3&j`T>foJk(Yd4NW{_!t1pf7Y&>DOxWGpp&prEuA^6gX3uSz}J6IX)#gd=KQLL|3 z$#c<0)3A%Db-`Ls`~HFg!LA&i`=azs-Y+G~Rh&3&SaUdV@bv@Wa9^2ZDq$@v zepE`HM`L##sXM(`?hIi%Xv1`W4A@(dTu<6vXmz(*>d?7a>ZMqtY*Zs^Ju8tNU1vuy z@3F~!L1t9c4Z*9}_N#dm4T=bC51lQ@xX&0{vb7TNV*p#aCJTe>zAn;O0k((RA}3{J z*9j%jynY0;oIo0?I$lFr`R2j^f5=6EgB`qW4`MDtm5Ft*CYdR$6_n~-HAdrR4=*M+4>7{^baDm&9qc{IVEaoZaGN&n6F*vF*imyFM0 z8hbxKKq}ZG(L+1#%b*-s;(mNqagqK#rk3(!GY*KEw&I*@Y&Snbiu`-Pb|m6MarBK& z(m9EzLDV@Aq!VhbtCMldIOQ^46b`WU@Gh1U5iExSm`%oo#U=AE&cj@((V3h~<`}=m z{=|7Ozn9A{@|_%ijt}v?vjfB3ZFt@h!ou_Kfc%y~Yf78h52OzmMm(~UL}=`iqA^h$ zC`vj{X2y|fPhc(*#cZM-rMGWH7EYMXdrZIqZ$M*gINkCsj=|Ew$UYro;npnyVH;r| zBwsk<0kc*mZ#C?|y3sbncCc-PY|>PAY|4+FSPPl$EhutUW{~2T z6L?-fC8T-U<$f_9HL`wYEGY1>Wx=YLL+Wln=r~Kpmh3En?P|z#+UVBJeW#R~Z9C+} zR>%jQ4*|CVSWT%gV|la*u#Nfz*z$Aw*?$deP1aVW$0|ua1GXxCrgZtw0$TI)bPv`{ zWR7o!X&^5+7fS>P)+IWP>_5jJQF!s$P${Caxgq9Jlz!6@b?419jT)=hg#4C!-&o)} z?N97WZ04BH*SQmaz^vywjgwSTEr)0HiBk+}?h}D+;Y4KY#l;1@=kbBjiQJk^wqdqCjQNg$09ZOBPj*EF z;PN#A?OaC)^X=LeI>MM~<7Y#d>j_Id&}h;tz&7ywI+!EBjEZ+KmY$TuqESbx+TBvdLQ6^0=9o4ur=9Q6S(GV7h%5sXWR3@)?{V> z)%LHHA`{3|t=CbqTZAp5tLNfC53swfHAXd>Bq#~S2fGe*YBEC^aL$-ik(I0zGAPUq zi-YlY>vc8$@TsX4>o^Ir7-d61%ZQpv3t397uO&bu3&}c9vbBt#;qMTPk$GVZk;MHl zGnUe)Dj|mM2Omz{uhR(>M?7LmZYZrGOSYfIY%q-VRu^(^l}e|**EMFw_2G;yfo=ZL zb0BjpQZ(l4aq@F2q2f+(H0FHNkYovi%L(u14wi2YV$EljT2p1Nl}TmotAbK))%loA zGFeOlz8&vHqw(Ko(LbzJHi4^{QHjg&ncJ|*j`Cb9xIO!R`I(Egwmk3GufOgdQiWIpf+un8i$xWMHPT>_~< z_K6deTt>{JCc_qSL!A$`XlCUR`G4|L3|kUthy`e=pWL z6G#PGG1b#&jlIssQjx8yvNKNEI2Kvz?SD~J8%V?zDweY zeB`{2Tx*MfTLN3kU&U0)eHmtrEkP|ATLHVS>%!R1hF!qMyiQ)Y-_(Rs-X&qra)-z@ z<^98Hi^L}IY;sa~u!$G#Zlq{x6K(?8V_u7W?_~kG8Q(Rjb3LoEZBqHM0cr(s2GrDP zi*n_FT_SnrV}9&EV~%ZB7R?Cod7j9Fn<`uGi!qH7NvuwY3qW=q``-_V+iW(_ByP(D z-RnV%#P(=(kGdP1^|b8nZQlpBbd`5tBIH4J_?4Y=y_P*TYp=`>zPLYPj*@G9cM+)uYrJD_*MvA8U=uk$--5=8?kE>h~EB?~9G ze8c5SI*IQhH~kh+nLYPa$QKoE^_2jHMZ|Jz7(_zl=c{dt^9*>w05b1YSAhV0q zP`?03GKec7JJw>Z)7sMIm>p(YirK+N7hy9CmU*z!A}ZruHVm3Rs?Ii~?#eSEhX8=L zZDHg_->MvvIkuwF*Rep>%?v_|hh;VawI>I%@G?HoF4E80r~|94vn2p0m<^I)X1=mh zSZ6AcD6QTNy0H`V3cyw7mXc%zp)_{VoLLi;s{EKTWRvAxrU}&VHKUH!WNJ^htie6k zOpy8^+p*37P}r3c99^p6NTTB}dj)+42#B}{PUl@N_z@)1p}w%ahR1`Qc-|Ali@pFh zh93dNeF4A4Itw`zc$$w;ynBeM0Q`R(S}On zYB()0!7YEE_Y51qM-)fAXL4D*8S2JJe>=tolbHB=P~@$QxS;_R@0rsQf^$8c&wRn6 zrg>DYfZWO~o(y!VfmCl2D^DM39y}N5jK8a6oNC`p4V>!WjQfb6-PywGKYqq&S0_@P z?N~@A1hg)+2L#+Iunj3An+(Z&{Mk}l0LyG#oJ{!S{rMh^2O3R!FxekQ>YHAvA!f-G z7v1@c=NQ0eInRw6aB^IsnU_)-jp{M#xm_GCrtq{cF7>rEhdOTxW!BP)VN|CdlSWHX z-P92j*YMePZWZ88B;%Oq=@3tcpW9+UW?N0T2)1R^)Dgw(3+4#Jt<*hJ6~~(D+%}#M zM(}PRh*7p)FUCcN96XgFpRu)J{n;mA`_Zn*A1f*TnBOO`{k`@H*#5=9)&#HwwI2&? z31WW@a{p>zTeI9i&1%I_Yb!Q=UTpOA0$bZaffFPa_b43=Pw@iYW9tgB^>EhVuu86vpL zGFHcF!?f20q$WfniDFKeTdf4+!_Gh-oP-GLK-Nx!&_VnC><;FG0jxRflGmGV)yR}B z0*8+TwkJP70n!HmO_R!1VL_-HQnX)7}fG;FdYCWS`9i0)7V@zmM;oZ~FaQM9{|X=X=bI-SsHA zB#36t?R?OVO6sKq*BfxpFm&L=gRDI#FXSc-Svq?Lvj~evz~&-myCawjS+VAC(qm*i zi?mB}&G|PO=|lHp8buvDO_Q;U(s#Ce7qA<+h#l7#$U46g25^p&_Io|R-m*-p*#G3= z#uH8O#+v3v9*sspn$&`Ge^@JZoJQ`+LlD@mhMGWNTYd8i$Q){3Wwk1*Isvr&DmGq2 zb|r?`Q**}p#9R)TU&2f>iS1+@v%Xfz_{7#Gz}lc1U4He98NV)HLvTwV$Erz!TmG9) z&6s+Dh1MGq`$YLJujOX&3fBEs1jMptHqQkihdLuO>W6i;1hsTU=9cxfDn;hMuVUA2 z!D7G#kdZ#h81hp_BG4GB05E&GuG2K0Ki)+RaU4~XCS+IfD&asXZpBLY8n%O%DXe^9kA>tGxG4{iqj{YS3iY8rN>5AJrPam#wUfE>m*kjI~ z@_jXS(pb9PkNL0-n<2A+)MUuias)PFD@a+e0UJRz)b|(EaQT_D$8~)WXDX%iKEF;DGZ3qIq!D@7V(#88yB_CBNxOV--m@`)Aop`*S9hUz2U+&-j`)%gwJp zvarAWw}99WuE-w&vvNcJ^r#;KVP2p6+iPeXsC&6x!c#zrE|jl_IzI)comRTvw8`Yx@b{&<%!!?r~$2*Pp zFQ26>FR20(pBj{SH-LN!$>%>{wm&Sr+iU$k1yZ93+Wy6WFu+Eb0MD zSyhZ>5rl1Ua{l<7|JxypD=G!3C@bfHolT7Nlc{xJVc7Ev72W7hrJK+$@-+T+qF9P)gpw5N-F|fz{*kdKn;^O__ z061tUIcU9z^1>)qhP}vJdSri#mP;sFzXTnTkM);Z&bwr8m76bnISF0~x(LkLpo}bX z8`!dcwAg(eIZcna;qDB?aPsCgkWDKo<32%DMOEv#Fla}Ky~~T()R|j zX)_>a?m^Y20o_{j)+@-{E`1iT&0BR?@_3Pb`Xib&S=uL?%ta3=<8z?FMJpGt7Z$d= zJJ_9>K=R>3r2E5&TdrZ-`W1?nD-t~<(rD9lF#+1A3$3YB2Co60JGx6(2>`8Euxq=5 zjQK0+WoEpJuyw{Os2Z-wYwInkwE$xCRgqoqnL89KuDOD}-YeKMbqN6G@gP{PTd!i@ z%J=F-+}@4VTRx=6zC$y=0Z@j-hj){O1*Y%ufzR(zVpUVJw0apw^OK0*8^XNXh`3ve ztb@6@3e-~4DmkaN9_&~;Q89msJ>!4iQ2PZAwO?VM25F`icz0gGw)G2?Ss)>Ja&!tv zjz?|CzkGnk=ClG3jM=I4oLAMg!2Mx-0~h&ZY8$)2)(VQxzQsn&Ez(0qicsd52!*l# z@(qy7D^SXu?PIRSQ$fik0uj)D3SP_2RB^?YUqwMXBf7>#{cl+x%Y_uwA(r>22o zNzwLXNB5ZtyRWu%L~a*42%7iyk$n9Bg4Bt;`3lnR4rJUn{s!36?U?xs|@l17L3# zwV6?@-tWU)(1;CxFPK-GXQYpdqZ37E7j|448O+r!kj1rhiMzS%pS4E;Uw4-{J6Bv? zD49D%MxFOtWdW9W{tZx0smeUf$;g~cQ3MD1$zG|Q`>$$S!qhG z$)Fb zP4d8*H#zq(jNIA?aJr*PA}5sK?@BMXDwFVDq@h_|B@QDa`={@)btj6o zhz%QlE#jUYB)q*c#Kg(3!KO!p4X;K(ZaiX=C>+M&#OWaH*I>)5mDi^k4HWo18FI#> zLyqbVSC14u;z2XkA`Wccj-fvKLOF`>?JD5PxrIeL85L!^Lt`(_h2=Eri=#+A8^*@4 z0~=wT>??D3nMKQark$OfbyB&YL(!u{*>6P2XU2}pB-ak5$yvVz*&qR|S>~xtuK{sk ze=Wjp^JkfWMI_q^m$sE>t3k%kp;LLbegjfLlMMcTGHgeh24Z0+HUf66`E4R`-V8ZE zEAD4L=D_@q_mSJ20+<8KwhGR<@+_cx{2oq^DmZPHl^%lzip2!B-oM2AuWv~-&-)=e z-VK>B@xYJ7yYF$F-%{^!+7K1kDX(>^TF$BKXgzPvYB)Qt;=ED7*4R^w4tVj(uEk8q zj=88E6EPc-qmLznmf5tjKWwj{Oqll@=bH9D(j@SpfuoHT#DDx2b2kGbt))zLV#tZP zM?51o<{-z)AB^%Wz5mNJaW5|#Fi1X|g za76ISjAWW~?&0jDEIGQTXDoSAx3Z`D;dhfrjC`*cCs& zvdsG|WC!<|g`nwMK1|&7;Z@9uu{#lLjs1vvVhP82_DZ*&2fWWN4jyk7%(&)iR8d)( z!}Qlf7>m(ynPyqaTuWuxQi9ExpP+0P2b77{(tzvFxSzk1Vat5mzn5XlpM4J7`p@`X zwlVzL_+QW1wgKyJZ7+h__G|dPe-^O)1p~|e!wci@f!a3Mxd>MO$iE3}&$ZWZuDOb1 z;|}CzpZvio^{Oz#z`A7lF-rn5!h>&TfeBWL;o6~kY#XSjrYf+bfs z7T9}z%ZI|N$2eV@RL7a})}0NYxT(O&_6CsN0FoQP>?F$HJ`j1_nuYz3T5-cJn6IE< zyo`eBI`XC)*f#Z`VC=@e}vHRbXoqh;IVPbtS#ctpoW@V0#ls)9=uH{}#0$zLP>i!fgS~X~?qCVK}bW zA|Hw3@W*F3qv_Au8jwf>sU0A_3v6rysREGM2G&<_Jn{m?TZ72E9b$^bLJ9L_xnRwN zeJFqX4R}vrWer&4{$znv8c3$p`zEr$W(HVE;(TER3pc}<_vnyeLCB_nEt%}J=Q`2^ zk+v>zIcC%mS=(O%TUGdwqJ~ugTY_D(yxTTC=IjP+-WfuTQn=Y!U~xs=%j{P#WPsf~ zkk6=Cr>%7yPmE&wn>!+3+aU1s_8{-3LvsgqY*)pwY1`T*Ijihv-F53wcJ|7??^!jd zTXm?=$jPY@08HoNx~)^qY0O)88?ogvVR^`p;+tncA_*i?Kr*TBo%ANa#b0Zjt<2$Q z{4I))A0QreA>rsj&Uys})4yX||8K%>GXjZ!Ph51J8f^15Er3h8F#Q8qT;brq34rB$ ze9b3D{qXnl4y}N7_7Ioo-s?39J4XqBqA!Hfqi+B@?5?i?TN^-p3rK7M$+$48$fR&M zH-YNd3v54qfaL8k(n0oI8f1{o9CPe%cgfl?00CPW>9?F7zJ ztEjwxh0WXj*tA=aHEK~b^MBG`TX2-sS{S$q-aiA8buMrHxXE(v?d`>!$m z7Uj3kvHj!$62mcUh8@`S>5y=DN#Q2L0)t0`ZJ!R?ej^B21>CwdSabKv-`w5!RoDj+9R?S?;T0JF*XNVxNXvsZ}7&v8IlFW)-+F z2xyD%pCbLkO|0K`VlASZ~GaAWs=V# zQhC2YF}`6lQeiWM+4dWd@EgF~Ujo-mz=%ws2RVNiGJ!6n{Wp;E_af=*ffNdSIswNt z$Jz+kzzCu>zXNOsAoEU%>gVLxE=BElchifN=U<~TKZcX|0+3z@w&OrCqnNi+7H2yt zob4oVn%+QpW(>=Z?qH%Xh>3_3%vqg^>hLb47l4y^@d)+BNu2UJFYtY~)N`h|hSTjO z93#(YGN*{BY4Lk?kG7oL2J;`BJ0e17v;P|D%FlE-^f>&%g9f@#nQw3n1}?$C~qxh$9l|!wWtv*Q3IA@1}ya(vD|OQ;(!_ReP&^E zRo1RuK>13!-13t_>zK!hrmvYVUx;e?T#}-a9TR2T` z;UpbLd36b;g&C|oeI#B2<6)bCT3(y;JQjUC2VP;jmuTwN@0YLD_x}X81h0Q@{0VG( z{*|1NKkjQAtp47%-jXc0UnhW9d--=6TZyk>gw1b^iy-#b{{5c`Y#YYQXzKn0$J)Q( z(C`Hsl)0L&Az{3Rgk6hl*o`%}6>Ba#)}3~2IIZGxo3vYzwwaN#S+Ns}AsY^3&22`~ z+y!WF0A#uK|ACtI3mh1~0RIl7b@KLW!Y*>#HVvW-xeaUydfV>E3fSJjp`k|%X(}cS za{3-5O&X+K7Gy#$4I(S-Q>Ab@oWlp6E_A^_@60cA)0y zRC&CHFVWC_g%kZXoas9RAT~5trBF~YcA{kHkbL2qrV~e+E}UyLIMZs;FlbS+(j{0) zJNX`mn!n;icNvG~PHgHfW7&KiD-JF=t;jGFGvL5nz=HQa1EzyE%ml1h4!FehCgE~o z!=Oh}+l#zWBL-kBWYo+mkCjZ~u0=0y(7PrB>V^(s^v^Wc08OX3A0KEtQPp2V!FWlS z>6+vFLGQ$?L$9-;U*=4J#qLEZp(~VdSG> z&cYz9N(1e=INkQ#^}5p#>9 z@}~AG3OBw&t@{fB$-XF3^b$1GIVt?(SUJHU-$+NY7lp-^?mO}yC4!MT* zjU8yPkYmwe!PJ9U_NcpEa*Q@y9&C9$SP8l@A8=wR?88FPhn0X|xl=mrST|~sH1!Az z$?Kv*6F7S(Dt7kv_Mph?#b!mxVH1E`v~s_+s2TOr(oi<*o~IN zK&8Wq(}4Am7hBE%l8z7(P9L^Byq|qo4tQjrxL=!teb|Tw!JgAqyA~<#gQp8M-!&;r zl}vPj)}U(Bp=#GlFYm5PMaGa-E_#iUi%NEt;J573q2knG*RBd1EWCUwxFxXV`xMPx zDA+V8c}&QA%!u=|IZQGaEVyl0@VPJ-^kOFH!*s}psgMuTVLzs00a>(C632xYjk@Tr zO!k+bq2x13Kk<@BkCliWTLS^424dj#xZw|D%^O4_+=s1L4C^c{J-M=@TAn!9F<1-2XO!41jC;iH7iGZIB=dRZz$A?nhto!qT zZNW>X{|2(29$`GUygG3?=jTq`3SlN}#Z<(OiS~$EF(Jc(iKqq3cl=nq>BK_RfW=@J zHhdk3d#@qsy^f@pKvOF~R5EHqHeu3IAuAF=qX2vY)^ym0OvEl*GPMbxNf_I7i@9y* z+mcZxNEI1(#EMj(6`6<@xkwK((O#q@JxGUjNJVr=g-u9COh|+jz*(nKB48CzyBc(2 zHQ)xfp95@pj3)d>0e_T~F82APr+YCL!dx^c*ZC9yY}Aj*SO7D9A<3hkblEZIR3JM& z=s=vzUeJg+uL;v0E2aWYOh-JJ?(=~_g$(TUphL1r*&E6X(%F~?Gf_8292(5~c?=!M zQL63MVb$G>`H)Furp!jAf!ac>4=d4rtVjB>8jWGGKO(uXOSf)gJ{rT4*Mm(uP6usB zgiP3sn6MGG3cEe$w#t3GcyAc9-`o|`tFc%V(*uK;?(4@?EQ*=_C>DmI;sQJyBr|D6 zvd@J~%pvDoj&szDHOBP}Mld(rhvnNhvA~ETpBFPepB%G=p%@l#^No(~QHp z8N~WfKqUO^XI&U}NtDghfK}wSWF9$I`dxD05ty&{sj<;-$9kU)>-`o1wF?nF=0aL5 z_8G7?>;WCAnUA}2vmcvxhq3kbJ#0LUY^L~LNc_R>&L zoRmiccD#>yuzY_A(>J57(TC}q7sk*4CWZ$v^UVXyeER_JhhrFv5UA25%kx3<+y=HQ zeL<+<2c4qVV{SQC3!KCL8~bd3Pip*oKmXq@MgA?;_fN+5Hzdey0NdWSfi1WE-v1O} zdt&}~9BBRzYTEyced|})_jaM;>6XO@tI5iZQuPSsTxJyQX6)LGs9KGvSgnX_4M^J^ zNPBFkx{QFK2k86)wVr>IeB6dnfi{{R(Iq+MWbYsikdzS;`w1`hhZ5M5wPm~w`*O=Y zS46&iWY=Tgp-0K4Mb^}XxV{4f7)8c?*tICw$)G4_RBjplL9?NXp$B`qE&+lt-oTmR zDvq>Y2v9n*GB20X-U|j&e<1FM`v{W;&??g>{!K=Rq^w44n@uQMt=Kjikuw=Uqp595 zO>Mn6WC6g~4VZdx*z*Mr==w_*+tP)GxfcZSC8HJvgAO}-y^NyXfU-f4ik^T>8E_F; z6VQmclKwJ|3hG%>}x> zTYynhcNu5BmjsL)IJCk>(b>3Q)ysM3`A@mDvgqD)>k)VBg{j(cS+HX^p}>7K8F1>d zf-x|RhGCv5rM4xj0eOpAjJ(o1186k1%k!=8m7LmRqfy+CdF~`i#nu5bwPgO!OjmGX zyo#FfiZHinYd5l1GjcW?ayAPx4x@6sW$&Du5g|tGILs0=Q#2Y;*6DCy(&N-_#EH3E z?qT?hIC5#l#XA`=NTqw;Yr>+#f)$4qn_ia`cbKJ21}Wq22Bo!Uwobr&1$#aJ9~%09 zN6mBzJI1TRywdG8=e8m1va0iLrsJ^=b&C;)7AuY{R_yC6*wGuX?$m?FucFnojjGFuiq(vU-GC#H0S!kN8qOQ2xw?dzE!p+hwwaMJ+mN!@kak!k zySiYrV%O?G+2%yq;Xu)4$F9qanq7}0OD~|iAw`R(k&Lbpafb<;E(Z#BKX$DF6deI< zyFEzyJc#=}*bLGw(=UaK4Zl}_kr?neHPW-YZNG$^=_~0=E}M;#l}v^*ZPAG#8>OEK zmtG1Hai>Ol*)vX!%n<~RWrqQ~0{pp{ol}qf0Ux%5Hf(szQdmlOyix>6 z*!@xvNZSKgF}pBjv18ilz?{d0WtR9y9=kr}GQ7!taElpnlM_jk3+s9l z){RE2nQU0MII-pSBN>h&83~E%LQIEzdLc{A*OBmbAmzJ`l&@1Ury-*N(WQU|vmPU6d?qY}t-`MHJy`@G2%Gch zBuke}Tb!Uez`4gHTlUFrg=~mRZ=y~1g}<{HF<~jtgOxxRmI7T^4)$U-pp~%})MG7R z#HPqlt-_SkP>AwlvbKu3WsmKr_t|a`p!a*R)$b9rqOFhy z*5SmY&4o>;2YI%WFkZ>S^RGoBYC~}#h+Hg;l~6#;*j@*Hc-t4oWHg3Je*lYp{g?>_ zF%$L+Me0@%$w3b?11@|lPFTgvX(QsnV#J4;NB|4b5R&0O#62ObxO~#qv>Xm$ zwLc<*#&2}$-ntnQqosw29UJ$;Si0-SXv~b!m_^t&f{uLh39~DGul*M3 zhhSwE7H#WTrIu>B22xeZ+Zk!>5)wt?+G(qsEuOl|x7 zzsAyD{N8^iV@sB>Y5NifroW(W_;*w-U!h{_03A=sV({U=;i9pI0bE>cxC}@-2xJY& zS#`)+O~~4v$hchKf@zxzSZx>3bqQ7Ne_+o+#*pAqx%W~Em~Ke|cj)GO!7!<9YD9LA z;I=*X1?*8KO-ZdXd!oFN#xVqSJXU-94&|Cl_NFyz1|{EZ8hdbJpzQVr&WxP`jP?y* zVvoae>9c|D!L={ZxcU`}Jy(%4b|YoeBWW`tXR)GabI8cstjO8Ta?HqL5pv=b$BB%?jjY{`jNOa4ovg9}TefbI3M+|vhwNKL za}6ckb(FL>Q0eVLqqhrnt%`8jc65D^dFCx$DAL?W*NxroPL#W^qo(b^p-m&vFnRNJ zq|IGOSPk;`;tsDYCYBuv++~<)X?MuTIUPv4ECNi}|Hl4YUPn#yHFf^pJP6$M~4}A7uGzT$T>SuHGYMf<}cVce~E^biiB&(8m}X5 z(ID%wAs2MZNI1=M&v4;ha2Zf>Sx|M_P_|g4;IZ!13X`_y)Z@_BBg`*je$v4%Y&m}$ z*wQSjOzE+SQspib?5fwbX1Vr(wdMDzqS&-(kTC0!F&j`c=uk8;OS%^V^ytoN)rhRR zVliOPqQ{=07ZuHQlzK1W$fFS;PgOv9vYI5Wga9_{@+0T;BklGg;qyrT=4!|zOfnZ- zWRf=m0f`A>bX1bPtS-unJCL??AY;%VZ?j7-D)(!{tC;$gumcMr8|Fe*k-V)($xc}X zAZ^-pa*uKz`@FaxEebq-4kb$_gUEl2BQvvD{buBRM&!Iof=Zyf={Cw-%K3E7Z4#Lv z8PK%fD2wv4+k~>yD1|u|qY}0rtl4_7?9dBqO-6ge7edlMfNXFWrM`Q}hKH~k?Z=&^IVCHPf*$=KDiph9oS%SC45|H@0tj1t7~Y zi@K2*ieUX#AC_(pV0Cy1+qdo`H*g#A*bvrY16b=*u|9L*0H*xB_Wg1%@ID|TzJ4c$ z$v!tmLRQS(i-3&u+k*i zkMz|3{IvuNHQirvV7`n)`wekd-8OZI!)Ik6faAw^aq#pZ>dzmd`uvfMy&oUS_l|$~ z8qMz?0;t z63CJ4E+_PK}DKWrPrm z31qZtG-@Ikv9@DoK8>+uWDY^VvCo0#ofr^kxK&krC8K-pbf} z^#*%Cy+r-lGt|HP9{Z2KmcA_Z3$kyuVCWKA^p36vMVA%Tp$N*4?trE=#nGoIO}xbJ z_$yRLUt|Bx8#G_P#pzFP(RlI$viF9?Q88)nMZwUC16_xbJKHokaOlyrn{Z;%<3!Vq zL(O$5B#?#ASue|=w7hQX0-5!u-GCFj4#y4+%C;LwnXh5ha2Z^Tq+91i| ze^vT_Yd5_(`sofD@197%98ErU$6lZ^_8OJ9uTXvW3bpa)sJ?xS%CljV?|M-W8?oo< z!GV{+uSfbA6ILBEK`$!z?qKh`$EZJjjHB02arpWP4qraP;j3@aeDMfJ&%VLlclS~K z`lc+RHmx_Lcb34G#%4S2>qz>#ux`61Qe^hllCeF~YovFU>@0yT`>F|EY2379XYTDa zlx_hJ__Qq zCIgeQ6Wr?2u$V-Jz#>n!KZMlnK^*@06#G9u!`{muP_raqr4MV8{9y+?|G+a5g%9s}|&9dhjPb@Yhpg{D>o z>E$#a?^V6C%x4v_8!!o2WN+t=*CgkNg^!}cC@mCh2cayrcsGKB7vJJ&>^b(wUZXMg z4u@|iaP(#hwP&xe|7sNV_v6?deT(!DPp~mOD6DtdX+_!Zlm-8)QzN~1sk;NH{O}n2 z&t9SN^d*|3BRGCPf`fM>*c;_|i@i5*P<#FqyN~aSoPXVK7C=F!mY_E4QHq3u+b;WB zbhN;|i$$FtG3DC!Dv%*64yPRjvhywn@^t_8&`?RSzY87{lD7s>e)b5pSI>%%e32i(Hw#k~Z#pCL!~DFZ4-4<#i&$S7L^ zH5PRRuz9r7_q*xs!KSyXH9BRR3>n4PO7*qg5T-Wm??ybJ1znxR0s8AfWM4c%e)I+M zQrE|`=nc1Vw{h#sk^8JVaB`G^DAs7u;T7X23advuDXdT7a| z!_uG!@uzo@pJ*NPccZAh8$)$$43&3pu`@9uV}EuQJ5Qe@**7S~Gq$iS#;lm>vq+I3 zH{6fi2luh}@)Ztdrm?dyjnw3O6yA^HV0s4S(J|D<-=jMD4m+dI5r29gOZOvKyyeBp zup99^e(5WvOrL$WsmFJ*{qhO6N1h}9<|XQHN3lQp9*y@CIGCD}zfl_>L*eyv0 zS{A0HjlqkhzOXQuqdo`bZpBa;dx_G!*C@V!jh*q=a&2WNUrTfnO1g zEIt~<apOXI)FXAHZgvp z5!q(cjg5hj$fYMklt@Rg_2e$nub*IN@+GQ^?@^e0i=Fu~l$OR(UY}=s(d;YiJQ%t)QkZ(!@T4|}6D3|a?DC7@nY zPOfyjJZU+^(m8gIPR2!GFN@NfZ;|~vfRwjK-f!1?7Z?TotyNy;+S{-vP-*pq#)-ZChREbhkcks+bmW z4Bi78d7P&fP#^mN*;@fwL@|e$3_W{kOLy)9?WE*x6BB_lTHx`r*^4PlX)TT5Wu{0(4BP|MfkoSn$fCD?vN3ODT6 zrph5>xGFvKIfF8XJ2q)>XyE-oBc~hUbj-LO-meAYRg?_O4ZemQ(`BTsmk@Ve#)9KZ z%=)im>%Jd{lRp8uEudTms&p}CJ}#rd&HzRt?Kf4N5U<h_XoacbE9B^6$nsnK%0EHYdJ&o$aZ;%do<-TDtV9|U7 z@xB=9FJ1yPv@2~(RxyqlVNp@<(GFKS-T~@qAiW|^>04jl7G{uu=2L+!SxITvpaGSe z{hn<$xn)*m>qNobi=sz^l27hYvIPHkr4APrS1}pXCCJtAp zfO=lJ!_p1=U(Kg+s`G{}|21>DIBz0Q*JdXimr9L%PHAo-6>n zIf;ouE{^oKca)p1pU${;q#_QHiA#YZX#Ol!zSPp8j z;@4o^tC!!M3Rp42OjiP}pj|*Tdn~gf53!e+1{g)e>zc0Cjn?2b&bftd&D9dlx8hPj zPTspEOgNpIM{e2icE~P3^k|IdFR2n2PWExmXBCe*qx<-bKiX5*Y&nH`do4F;+X4%S`IjAIY{$5=X*)oK+74vx+BI?$D6BIfATHnhX#dl zo()GZ9SmXZ<}ey>-zp=zatWyJDkCczQ8oBkd5v+<{d`xRYsH1PnEQ4ZZ(}aii`pN+ z@^Ao?{T59088J&|c{VJNJGzD9H=ldl50fnQ)^D)abi?sy^7QPHjd+4h(G&5^5EY^!_I z%-kJD{@sW&AftnHv)W2Ipwo8C{hiLybat=M{4kE)$yZpo7geTRH$7t9MexpkYyw)! zl&O;7zsX!vqP;lyC$Rl{Y%PEG|GIh9|7c)a>s4k@pR%Q_n3BZb+7iGLynbM433T;W zK?abLP06YiIjnLs{`uDguXHK>t?lmt*Wdg39|5vIe=R{DU5D9gS?JXvZ?>a8cnf&* z4xoE$jf?q1HG!WT;q3GXr)P&aJ=+Jf>Qwv-?el9mi!UJiXh^X`rf%ff`$;#{7O>sZ zYfv}nu&3AIP^-gvj|S&GzYlCnjt=ZtRdmp<{Sr!+zhcMq7wnqv$UVM;!}y|1vdo8UobO8( z=PBcBPfu}ja)#4$rt&fUP9>S1RZ=KUzQWd>K9Sm{56qA4qPh2oxUgea0mm z;-txA-&8rH3@txB#`y^svK1gckH$}5Bk#8(W7Y|HsN5OE`Sd%LnOww*t9lfa9XadwFhD0>4Iy5lag<$Ba zL?#i`l0nQ{E@Q`V2_;4gIXY4Hc4Nza6-%D$SRAq-_xe80(o3xZ2|@n>n9a!~O(vO2 zKt%T#(A@b{U$R$Tls{{L}q+#^8_cS%=u%sAoE7!sEs~F zVkm@lhXq@1Cz5^rs6KxQBv?o|kyxLjdP9Ei=!~DUjzjE8t|RkD%h<=!=`N6(#nI!N zsJTsOn7grSydvy$#&ca*=24mp=25MlS}To{Xy!y3fg^(bI?llBvx-yH zJ`9PxI4AJp;=iE^ArtQ;#)huLG!)7W2C)78_c&TvSJ}b@dt7vanTt$z<#BJ|2sQZ| z@}7*?$fuBd_Zn+=hoq13Q-LjiZ`*4`+O0#v){VHeOU$kE?jGsc-f{H^s3ov1d$jUz z8d}lFie^q^bBkU*igf920o#hhijvzVCT+}m-2U-CPE)h3C=I&QRK5*KJ$kxSmwe?Hmr{Q_!G5ct!JJ?|6XdzTIhD_AMoU#Cx~o1pg4DxdEQamUGn|b&kPBI)7(k;X z%FM~U{^lT~+lqR+C_(1G32e89Y*_81xtSIlF_RcUZG??d2w4gm1k5f)*$!Zl9_7`D z8S4?thX@+!Uyj$8!pII2X{HsSe&8@T&!yA%+`{DkOTvX=as(C_1^_&330_x)(6@Nshnd?}%=Vix7c&UB zl|n+;g!zC*ddlf++%|)nAGAV7zYQ}n_RIS4zAqq7$@Rrq0j=P%Y7+Dxe!MOT-We@- z%ICrf&^(pM$l}}-Hhz49v4JRF1pSz}dkg9JZ`7Qy$NY6hC=$>zo1SwObCK0JLjz~k zyozor#F2je7*oSuj7P1qZ#3m&X6@_{hrb1EmH8N1+lz5OZAtQf^_IQHG>H1t?LW&r zYPwJL+Wvey6>|!>{jDwgr3o%Sb^BYu^mD)eFK-@2Fk8`liT1Xx`3hC-SNOH<#n-i8 z-)3BYYs)^`x=v-*{@RwnlYsG4w?7A)|CL`8*b=1d8?-1I_0qeU8yo@{Q^Wk#eNI3` zXaLu)+?)V7##sxzwI+CG!*OC?n!<)%CkyGSy$j4yRluA*vo}QQNW-H&LpPXFOLHjh zL;EvdG;!j>`@^uPSRP7})wry(T+NroNQh=als;EXS5a;a{+pxyp0bd)s2<(6BQsfH zkuICmIh6gl(BIpZNUQA)`3(FV?UA#)a%&0jF=D2@}cQU9zt{wspf5 z>2XyBnoa?@l&xNrlPi{8G3`7@WKijZO~bG?Z#Smg6R^u%KUusq$)?A}#gRQ@l+bMs z4XDKif%(}vn&&FYm}iZ^?;Oq6IUqDSMhQ(h7dR>kiZar0<F5?|E`6S<8)?8BF?p zSn+$Lw{_cXLCI-Ci9L<37E>+JJ36G;gUj(j9&AR^^Kp<7C6MHp4?BQ8X2Bi-XS}A) z)HprC+1W{}Ab5%+0TV3fwZJc#+(H%;10iv(RR)KY6#ub7=`q3UuMH(jR=v;cyH$g| z#UDr7Z$MnkvJ8?}OE#YQw3M6^Ff!*=Sk)#AD=c_6WpL&`=Uj5mBHp>WfutbByz^GB zbTWb2XcTjiC}#Txu>EEP*kz_GpUKQgSC0jCm+{Q;u2Vx!Eb~ZN#HnUcpZE#$jAe;f zq-QuEu}Lw8?$hyr0UN=OL)ca^ylOG80(zAJ*3ZGOWTQqb^1kxkVT&-eWNSCWHtA7i zpX$#Cf2Ib1_iukLaZrqe3OnRybSCClkC;9TWr$@KU`+!n8buKp(?OUZ>nydd03Moh zMA~H^&MUmG`8?!&4{qCw8WzuLSxnw^VLWEQyFL@%-*y9s+c-a|%kx;KBo^@aJ5;GO zsZ?pzlnB=N#TiuwyJ%(?@aComql0ct-VGr){Sw%t8ikqR%&=`KUHCpynBYFCGst`K zgeREbv{6EO%PA+iz2#wa?ZvmLj`u5&1N?lqqwF`P9$0%!_^B=fLQY59Or^wFabuhigUFH(Sq! z_Hmavit`i)f5^{$w2PIuKj7V9L>SwVftaWcPEKmF%25ZnRcw

PQNEoZ(dgfFPQA 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

4e&0o%9z9;vCMU5*ZH7b2#Q!0p$TihRJ>#;tgJ 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

Y=L=at@9cCw+O~fn>R)D5PEV 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

dPdp-b(Dxj)C^Ua3AXv-p&-;`Z;hdmb(?zxE z+!(WE=%BvH{}c6Ffd*ysU*I4N(Z#v>GiRE0s$PYcLk4XVWfNXr+29ahN8Z}b>AgU8 zw4PRHH)g1y5(%dcg!P=k-H!7|n7m}IleXpa2cKHBUm@zk)|#UvZ*qIol)Vp`krMd3 zY}b0q;Z_qn{Du&z&6++gJMF7xN9G?Zz$%06Wd?;GYHAxwXU|6 zUTi}ZdC6a!zPLWYg>vDxji@7q$$9K9vw5`m+9G~KG06yVj__PjEJI5s$NK^+0tw^# z2*ft)v&o~u_y##_lUvfeDVYCYA$;;DCJLqkAJ)?>54+*a`>Rp!EFcjBONMS6B-tE( zK;JnQ+VvLI#J^`D+8IOMttUL(21o z9CUk~4I9d6v+4FUd$ct9!wUA^Zv!S9d6>By+kAXDWaK~8_a``aQHUoHh48RDeh#KC zw)@HPa~*69Tk0lRef~2zk)~coO!N*B=xFfmOZQ50$b&5nY)r@Z&MS<}Y9rd@?56eX z7Csevd*cJI!`<0vxobJTLSF@=gTpC$yDPG--*vt`S+Nm5_oLr9@VSDtz*EYY|f!(%c93|pMcy$U?Ni4oh+ zKg|J_mBKH&R1LX_BS&jhKDWDW2N&8HXQ4Qw6!;};Vl8;NBR-124hoaDcoF2gpI37p zj4~9N4}~Qb6@2sJjk`4>gdXzMN|Jz*Qi$tk(gkr1^)vyN&W}M0&UeomobjY-EhTlp z6zF1(BBLxE{%FeEXP1;@7RtO(MuQeco=wfKUgFQGk=g2@i-Qv2gV zf=G(g%Kt75o%RpKCv9DRc;ripY;=h?xM|2CVstJ_9p(}=JuP z)BvPGqnY0$MjR@B68^7d7SCt&ayuAV%lHvm&Gx3G5!DXWQD{1JMP9}GBVXr;6G(r8 z*IOLp1oeC(uRtuc;4eQ*cIpx{{j*HTnYlR$Pn`t>4P^|jQAj+Q@GArMHtZ7hY6sTl z6FPN{0XTpp8K%%#7+qQkq}rGD8I_wq>Sd=~H1#ta-T7+OxBg8+rQ^)IR8Bh05$QRu@&QiNW> zenXJDI@RaE=C;^sD-(fa*;mOH56%`E0)}kvvG}T z{wzzaM11+8Y--$t5s$ip(xLnQDhZEFK|6;lC&Re3o~Wwr!$OigR6ZLz{DT*gbn=L$ zY)pUP;yF?L2gZUEfj#e(PQdb&i`HZ?y0%X=F~fcTs^K8dW8LG<_#Rwapq(i3%|!0P;3i#G%IapFSTXo$^#9I z5^`1A2zJltBqd~SUEVXqtNix+-NSnRj(r1noAyg6t+^4@=_kjEBXwEsWjoNweZxg# z>XN|{PXtQG%0n91V>$`#GtP4kZ-RWoY|EcoSR!qfRe8k{0~0LMbD1VN3_t4D1#``a z=69I$B=&3HN7xaiT)@UrE}?nTM(I7+1Z>ki72VCHZtw52clSKOe}9_U$`?S3t~?9= z5h6BdP(EO^ZSkUi;Xm&Wn6atbIqVGK&t(unnJ2~sa3AB$Mx;ZU!O?+;c0#5Ns1wi?&pyqlF0fmHY*6hF+B`B`Z_ z_5CXQap|%jna%nv;609;sh{cOrkx+DMk|RkR4p3DI2kVWx#&cy=tzp>;{wgXzFzgE zkM(<>nKG@uHBnUh>lEfNk^%Gi$YT zo(nZH58LUT_95{pO zvPDPiGzhWx_QE)75f#M1HfAnI$vx-sLAO2nAyzyY(GD~SNQVSfo8?yh=w@Oe`rK<- zy@eiVdxHUx(=~8Hl~@fyEkGxWa0ZLP!CW%qcw@RcCG6zgQF`Gj1=N$*u+R$ududIb zsrDh(5|WqsN!syIVbm;0q8zxJb-Axe1Na=FntYh34=MO@>4-3X^dBk8uju>J#%RwE)tFJ405N*EeG-hQEWY zltfAhta=BDiY$)Ycs*CU$xZe6_~-CoU}x@U0to`eUDBVelg&G=)t=i1cC8|H1a)Ll zAD2GDP8SEbCrg=Tug7pi=0D@-VioE~2cCvviAPRBhBYIxg0Kt)6E*Lz5eP;^g+=)7NsK)8;^ z{iBKPt6!We_x9SflSjz>@mvqen@Ksx>N3ttpY07?goPQ68f1D@xUf_}_v#OyA|8mF z0F)3$2V%66cxd^%FE;i38ms7vlJb1_+bU`4#rj`I0QVbfQJg_K%g_xq3se9{;8N*`+9 z5?cp6T3}CKBK9+J^U3qBlX9L^>d%u(=lyB zD|dB~@B`JQM*|Qq;)=QBbl*-T*_g?HuYFgk2g*HxE@|2L6O^_q(BsjfFEmeuZEB8b zJ2ysl#Fubfy|cmNc6_kLW^SLO7y-rWkU{^6DJM4c{iaYV?E7tH?33uyw(r=Yl&$^U zJ|OQ7}bueKCHZVD9NXFu4QrdTiNmUlncd3)JP%qyJK%b@Yb#wTR@X2sP=;2S2gOa4qZZ z$p**4iPn(wvlY)L2JQUZDlu?NeLG$xfR=?3jLSG3bVB$B{dJ>7K8WQgIUJZ3o_&{f zW81+>VeZlDy*&TaS5TmQ4jhB!-t7p&RxBpA)kVM^I!1{2%bm)HZDnInB?LtZ3qjLM z;~;Aj+>7XbzTPn}4e7LK4z~ezmWDOyf2~>%cUxjn2a#jLJ@|-p?wTmC+Vcdv+=n-5*P({j zVqbAPsEfqe89?g%KH~l}MZYIa#yM8Rm;USQ473gk$wV zV#Vuyp;oK#ycDg-U{cd#@spP?)!(^J9CdoEQ9nxXTHou#>}E!yLpY=IHd12sDFRCJ zGjMdXFki9nRsYB0715su142unkodZ|`-EUs_F!mU}%<$gH z*iZl~ltN}W40PM-ns`TQUpx`lac{8EHNGt33w`c`2z7H&YAwdkkh<-3jjm@8)ZAO6*$Wj`IJ zw+w6$8E)F_!YKwzlH|tvAgwe8luO~^hS9Zp76b+-Y|4q&t>-x@OxCaN+PSFtHSW&} zQF{dhy(Jn7$G-7IC_q(5;!@f%t!yz~kMU8A!qe}dIFhuMUc45whzXGaFV=wvF)t{R zw)n7~iQDP?8~7D>U@TZh zF{NBCQvSgBcKQ3sAACgN7IuGwNEB>tO2o7fxIja0gFCdgC5KJpw!MNF_&sF*{x8|e z{te;KxqXcGFAA&i+N~BJDtP$h?pFh;Q0M)eK0|y|&H9aYgL8^-A7WuAeQAl@hBj6_>YImhC0hnQ<-)k@>fcrmrsp-e_KUIm+@h5>C%e?SXGjDvd+E+|{sT zz5%da{oa&y*bizq>Mx%sSC96Ra8eW_?3iu{5j_SUeo=w$AqPECXtrvmKTnra3fac6 zgevT}QN5xZgH3o{wf@x$#AuBzrU+ZAAkgw41qwIw+v)nND!W{Bf>}XXYkKMrX)OY8 z2c$x7`XPIM}0 z-mu$knXmrc>sgj$SB}HUbn*8U_QQN*?2_V}P?M$g6a;!W!ER&$QI(K7vTkJ&BnSN} zBmc4bis!vv?GESH*hwe)1AbnwAzv|>xb$HG4A!Lb-6Im;b>`18usVgffjntjNRSPx zFR!gRDgGFFtje>S7EtjgOic0$)r&bqV(TMqVILqqW|_eWPG`t$?mAz8xT|Ph{N5Ta7HI)Z3&XHhu&nQh68aPLx2_qJ%##!}(TdX_oztd^ry;H?74#RC{bW*H0W2 zMG2!vYJS=m3VPa+7EFQByy&BFEdHs3uO~MM%GX6u@u1F>uGf5Ha)8(=4$9Kj^)7_P zYm7Y2;SXkEoE&4NocTsGbJaU*HZ)j!wu4f*coc?Th~{nP>5IKGCVSX%xOV7;__ zQm1HS^l*vD?$ovB)^0h#BF9LR ztUmLgC+p+B?~8?w1YE%i-Sv?Yo^h4Fr*WFS-nQ_S1Bt@H5P?q#NuNo3`!fn(=gQfl zFA}ok4&Lkt3^8WnCG&E=GB_N7Ogv33{P$86Vm8UPAvzeDCB*7V-Ii_Ef7{^9{Goit zgmBt7b_SEex$a8Mbh_vNEb^_VuZ{~p^*f?;!gZ_j;vbZyTWo!kBjoFK15rSdC0)Z4 zd@cMMTRck`!q!tR{4mgg|DHeri(xxk0F4;kd@+6Az;nJKRD*Mfy)kwitPk$pSZXn- z1{JA`V>{0xfrBUX?#G=aMli5&UywGY$@!Pv*bll}aV(1|tA~|-5H;i8X`Z;vZQQFS zB~*?=3N94c5wRXz)1fq*-0`C#^dQm9OP$B>?HikK>24poauSN2 z$%>z6K~$Gsr2@Agk-E<2^Lyb0xh3T=9fvt)&F-lrvxf&7!@doWG!ZjA0pTP5QtG_E z@`d-IPNbF1yFF>BDn3f){>mS#BTQ@92j-@T_0ZurLJ4_|qwpi8m!PBfC5y9hdYdB0 zYe=Tt3}4=Y%iLf(z1aP6v|}T9%#AW7NjPsl*KJ&+c>VygY`b`7wSWr#ak}lqMdrkG zG%lWzI%cgc4f%5VoCF`$IU{)2#3Fh8wzCq`M&N-ePpxb>Z+Zm_tzB$1lK$n*3(lP6 zx%?XI7A@j6aUjX$W`;FDbo_Y~6mf2^^(3>1Z;@Jw*Aq#q@f;4Pf3W%9Ywi(HFrt#` zIJz*?g5+>^-g5F9W5d>J@UIZnm3VAA*g!Ic+{SYwc^=&4V zDLzJIzSCs)?qyzuOr#5m7TIgQ>2+P6>F;tA;fIB2`CpAZSbCbK)GF`1k`-aq-zxb~ zgNq-7L3w`W+^S#>9U{pcJjBV^-g}?n8PVb19lKWHP`^Dnt-8t?J@5UH_h^XS*d?mj zzgk!c06*f~^zH!7x{i6UM!U@&5A3Vrz*9|W7Mq6?sVD!MNCvl3sc~)6;Or-Q+AML6 zx{i6PX*GQJkgt@@9-P%fI$w({%zy{E-DjP9$ll(30cQWrp*1)5D*Uf7tr!bR`$#Af zq588Kc5CRg^<1=k#$dPj7lm6854eT%FCOG#lBN`M5DkmTxvX@(SBM+SZ58c}P=@Nt zf#&*-CW=XQ4BhX-p7=+V-nA@ozQ+xW4iJ=Z1-bk2*7%=Z@zmcLOgcn_n5ecoG`@%z zejPjZF5`=+?Od|esLrf^Hl0TXL6&mNn|}Y=w+i&>z=ISrGFeQ#p?LiiG6tIkdpIF* zPhy81=GGhMdQ{BBLDqx=RUH0}L%;ZBJ>m^W9%MAA)J}bmfxflgjVRnKhX;*tc*Ev)Uvu1!j;*m%au~gv3x7=Mu@4TK57D{T&y) zhx?9T-13qGFo(cT1X%`S=iD|iIsG4&ngo!I0T9e~-b|dHs9>`d-w$|^a~4=ACBP?~ zwa(PkuaOlCq|$7ue(K+54K6`bMrWxI5FNxQePkMMGc$jJ`gMHqasE&JdVB!FO1jHB zIsPaxdn$KX>qxD|7R~Hjre8i4^<^>&8#~jnmQ+k0yK3fM^G>d(66O=L#8B!G=&kH$ zEj^AD5V6Rua8k}Paf+7jFGbqxEkG&eEk+gxB@_GEZx33)Knu#iAu99L@gWT9?owFbd9)(1fr{Yn<(Bs68TV*riL|7R6?(TT}EU5-P66xN~FDgjnYo&(JN;BUD+7VYI z(RqJG`Kw2=kB3-(6Z1g*PPOYbCps&Y15rFzCHSh%F8yKPou1v7{7z?bFkWuspJ~=T zK2>WgGRr9K-8bHu6SxgpbEG1YUG0GNWZ_arCYm2Kl@y|Qp9oWrH{S?=OZX$HZha|m z=PRWc)$tHs>MwdB7{>Z_MKchVjDE9}lBNqbqKg>w7F!dS?J1we8tcc5mWc^>!bdO%XPK73nEH>e>Q7ahE2cSY|* zWMoJO?uz!8BJ@o_xj?~27j2h1k*H3`V^yf9pKHm>JMG@1BI)I}k!M7z%>h`>kXxASK+O%1_A4L36 zUvz-TSz7Eed>g#6e&&y|BRB}kuF>`UdAN(8Ohlx@k2q;idNtr{DQK@CaRn7btbou5 zaDCMRu_@!Z3!ixFArFIxK9rsLiJRU^aks%#GE5|gway1eGw0lt(OgJ>N%s{l-&Q5X z^2q{-V2Mfh#>a&8kQS;zw5Ackn!kp;&xS~oN_%X|MJ8X*$8z6YwtIX;UP~E4^Wm?A zg%DQ>&OnhmD4-z9>rqOzxuVmUo8C*uwLQ&QwEFiw>W}dH+xf~Or|Y7Zm2Z9<1O^)h z-5Rpce}fHzOS6o%4faobm-ngax#o@FE(?YWTi?1*kDm3hsjeSr z4Q*v&U2xTD!H&KAnoBA;<D_>~zgEixV%GdD@f71-A2qixJLO zn-kOA>r?Per+2tdU+cdWX?Yg3$Z0~u-pm5Ce zLkK<+zf$VsMzEeU=`<8D3VDUk8Q8`A~6{H|v&TCnA8ZR>=BCGjm3g_7UFh_~WmX;Qy zY(sZ@w*20z7q)n&ai>u6`v1minbm4_^#Y)0)(R`#x9| zQW$rzRbc)}vWrBpr3 zD-K##HGV1HD-AiG*v_}aS~E23Ko7Txx)&4%bIi{IKy(#Z@x*NLO8PzWF z`-XO>rncL_T2E+dQAG7;g?J^->~ljCMs&g>_hss~QhH+1({BBF|jVouP|>#Y*G&!N`f zJQsGn<1qEvU{&N3t&HcH)~EU(0Q!z=A z46m05k`o*V`O5v;<)3mG=2e$T=xT)IV%(}JQ6>)%AVNdms(pl;;eC=N1xUJ$wl|Cr zVM(X7@+bVw1Yy< zAV|=r+0pNKyrNGQjdpD_#%>rJ)9_ua8Od?5v`d9-e7IFysKYx_?)jAtU=cueXXo~- z!^xx3VJ)%oRxeM$AIqF?qpDgJSXN~O@DLOU)&lS7&j-F1T1IVtck%VX9})I@+3BqY00Xw;`Ya-zYWX5#3*Fzs6MAjj?a)$t6Fnd+m4aVFRc z%enhL^z|3gTmO|#{wEhQ7g?bBZ2g44di2s>N}N_0p+&-p?gI;N>7oNGF;8P1O+g(K zqMU9VK!1!|yqPF9ohNVBJlOnk2k+KvpmK+n(D##8XLhRM6c~5bICw272PKMdf_=_& zcTRfPVLRr%@zm32tmYX7ya-Q5vw{!8(-hrbWsZy5*_*P{WpA^7nP6m^pEDHnhQ-Io zUD3dL()c+6VN8aR9J}Sfng?FWjMV8iLuU#P0qB~JjsR4*qm7G#4e}f4)(hu?_yk3m zC#%5d;Tvh`@$W1&$ne%iQY>33KfI$Y5#479x*;k9$ALNFH6b0;{PEGTgS<<{-T|dY z=Ob4|e?q$^pa0@q*Pr+9v*^9#xikR4?3# z@pmlv+>c>5JJv+OF`uz&fdZ+-$I6c=CnFc=-o9#&@w*5VrAiRtaM{tpK`#a|-8*KN z+oxYHWa7ljOAT`NhTaCXO_Rhm?2zaf1&(d1mn{k71hs08cyBuZc=KC;t~}=-?;7hA zk$^b0HqYB39`?gpWM+No&Y^L0r=we&mI2^4_0XOzh<@qyF)}DtrB9fnRo}C=APnKr zDol$#8^^VenKex=#4R%z7S}#$aEE%iS;Uky8ilNtPqc4D?OtnwI^tDtrCmV`HG@DW zLahc)aF!uK2ODjMX)mJm`n#uGik>MB$8YpAAiByrf$Q{~%kzqB`8aa^w^@vY;BEKp z!1~{>u=E^4U$L&}Tpconrs@|KVI#jTdf=(^_XbL@n3V8Znu&UtY}F<Jq`#i8FmH6(SV7x6@uZ{=jyKOg6_Fnrv;6=>rXrC7%44 z)PX!uL&@{W$d9U2vLL2}M`A4|7yP>+QASxdExBzwtb<#d%#_iOwO#k~#8XOFcc^Z! z0^05*?GKiU&^(`Secs)d9amX1dEL&+Mf}&-m4&fd?sh2dRe9og z*xGfwL&t&Cr)MkTbNki(5Orf6rhR3a@vxEjykMwJf0%H>+K8A0LYW5M^+Waw`Nn_* zoz~(W@}c%BE7o8Eu2i}F&d@O{6&)%C--vP_14cFhxV*QI+q7%80-b;^{v>ck-Z%@i z*=>U(HWTmAOW8N$@M!w3%kr5Qs+Q2HD)QF6VGVHH;4EQ>0u9s-3Ru_XYQn-@-c;So zo$!U61P^oB_NKCTDE2Q&qivI@u8^tM#X6qU}EuGPJU7WCHCzO?Q6n`|tvPsl8X zZqxUE0X@F>H9r*%XJo&!YPbu-${HpM9tGDvM3z&pdJ(m4JnTnuNWie>bP1=tSfaHp zy%v5_+G9gc6`IDvUWj#@d519wJ1Q7tCZ$xc!9!&rVX=uU<1b@Iz1vMwybBo=PFT>T zJPXOWNtN7zJ}Hz5@?-1*lQmQzxw^41Q#c(^kM|86tZ4cW-)RWqAwg@2w}%zlVlBK3 z-Fc_?mYY0X+A?VQGZ_53)Ie?I(It%ES!ZhdMH4RT@c{zud`sMqK27IHnH!_v8o0E8 z$vJ-$sE#o0WE-}~tHshR-WrtAkilkzah3H5%L%g1|B5tLMx#CSXxhInKde2@qNye2 z$#miT!3#JCO#P{qpZ=kvBNh|DszXZ~blJ=ai0u3mFn`*cd&PG;Mr-BGZP45?Ksml{ z_N;8&U7@fSVFcNAdKQ!hFzX;%(mlp2Bais1`^Ar1ca&KIJy?+-C|giKi`>%_@fyjk zE%LZ-!Cn+q%*mP+1B>GfrZ%R8HVsP+v4f-=Y{WGbEg>iUt zSCRNH+oiF#hO+*iZvp?N(Cc33?!*irWp04(k3_u~j1%txtG+PSKtq^YEZ)HBa}&S& zyAlaVBsXf(U3*nJ6&+z3Ow$vJ2QNo@s2SZRv)5KYordlm!dUooAJA5q9;N+mo$(`V zkQ4jE)VnBnln2AgTiB>^^PL23whSGq3zGyd+0QP*kPKTGde`-5y>k<9ir6!}rbv zb48vT3cU;#CLD$f;UgwI{Gp*BIv$>nu;qA%Iy}7hug?h7ONkMB1}>ZQ)QKe1dZBb< z^^>AOK0((ulLJntkbt_i3ZN4Vl~<;ez4oXKv3iE<8U5R)oT+IFljecZWawBYG4$X` ztXhg!vVQT$6H5p**$!KhRUSyd`w9GxO6G{NTh}X+u-OdBes6|uDh4PfB{)z#DU+Wh zBfs)|A#vsHMi}^-7>g9S6(h)2v#R-BjBcwYE9pzEvSC9cJt$c;=`k&SJ1m`C-HyK- zr`d@&AP{UOxOw+0j=2M1`ZvI?`f9x!-^KRwZ=D)SSL}M@*I(Tw?fZ~Hz5UL6s%cK6n|ca7l(8+Vs%#3{2t3mD?4=E$|4=Y{_Q`9=(2 z*Sgib7osYtJs=`^%ER#6F8ujyauw3Z**U!t&@b?P@Rf(~0mymLM7(J0 zhx*#OU_dKvE3MpMVh51??IA_gh<(e$>#{yTU(i%Zf5Gy3$i=}%L*-x6>E+u2@Yt|b zUTc}fSc{`HHVFlT;g8lXV?ASP6M0=Nr3}9|!yFjg>W|!516wIV!bFegxDYgij0`gX z#_9QECu!nN7p@$aor;YHlL`lkl5(V~^e=(#xDFuR?T(`go@F`bWq^6#TtlU_ipooE zlZ><$Rus5DE{Km9SRMT0;N0b%X69I&zHuT7GPPycEE<3?v251$3{+9v0MNcF)ph|b zobx?o{fWiZkX8P^8(BW7lwIQ!c*#5wVFH?CeKHGH|5n=gF5_>1=J$Tr@ATe3&8u!X zVjqh40=S5+H(QR0kXhy+ zO<;W)=h!0wSTRdHnO6mqBD8avFY0x(dh0j)yup&+srrtg*tdzvYr|t82oCeGZ2deV zm1``$Tp|E#mZ6S~Sc06jAiuP>c$b&_ZDvcL;3;Jw_y*Tc^Bngy-jz1ao0SuMq$8a% z%A1kEVuNcvnSGl4@*^Ch&dK8e%28_0`xF#xP%pQ49ov&|MS*Mi&FdM?N;00>=uz4< zcO2nk59~qd=Q+0-hZDCk*J`9y6Gu&SQ3DI7m zEq%JyNMmiEjAPUrqEu<*bTiR_gU+o7ma%y{1Exx6&<1t{k1Y8zOhsXwyz6E)R%wre z3kB?C8e>b|;%Mh;xp*;f8edYd`&_<&daduOstupn<{y`_boI%t+GKEZ`D8DAaanhp zrt8TST@qbRA2g}?=MEKCOFs@7e5jIp>*6+F>_ePF{&f`VYj2GET)+{b-2S+Cc?Tl+ z(K~o|E>U=4m|1wRyr`F$)>7b8%?f|^-*i4J@jn{kingJ6s1Z^DJ#&a7$7;J%GE~Ou z2RG92nZp84qH$hK+sa7HWf_o2?)Lka4J`jX=}fp}#J>O|1bG0s_BHX02CT>XGg+1f zAb-4lks^rhp*V=NC~JcB-#L)RNBL#mTJtsPE^X4*!x?37(S}}ikVh-EhIx~Nkw=hT z)(2nwc?;)%1I@{t&SQeMf4-%g|3i~Kv4|PYRU?S8RHZAUqh}pt7mxNH+Ou(_N)dw(to=G>H*QE96?f{ zs`bwKuWGd(UqP-^@W55_FEyciZ^;uKw$GE@Rcl5T&S*fnM83*jIX`VS)1Sq0`Cmp} z!ei6F^_&>h4KS9`TGVNAwFxa;h}aH=v?m{H5)BKIWR9!R(0?2>H`k?aH+`Au-hrS5 z3kcfXb}{8Dg`Z@{aYxDj>j@%(%5NP&TQBT|<73hYm{UZycXUi}uHS$(-uZ`kN6;dv zj)=V(?UXjU@%{gKO?hs@tjWBpvD+$b<k`_`%BE= zj)!T$9sLyJ*#J3PT`_oD(u>eU*{PaMM-Fg50nAUChBl_MT`MMBEDYMBauNksfK$}~ zgHU}MEw3T3)Mk!VSKQSc`67>jG_Be6K~D*thDFQBJ!>KJ)Focj;YuKWtBuWHH_1O)@oyk8!o501swYw1|i?0ymsa!mg}93 zwoG61WV3?x9`h~wDvNUk)Z=S>W6RQsw!S!|7X%0%nFzLRKnB48wRI5<_m%tS2Ey#6$ScP$MI zOQ*1;NY`C||9kJJ{jhJ$d*;kDGiT0uo~&?mpAXDCR7462@4M%AJ?+JJ8_3Kt)@ zOemwdG0CfGgwF_Ys+VxTVEDkjuoxDt7?`sN_F~*c=o$JEQ8*u=lG*9q8-27v6PIRg zgxJXeoh|8oqm!?ygtxS6rysDIyQh%MDMHjqTWhh3NeJ*;K~8fu75R?%0qHLv+jC6c z4>QQvdLWCTq<&7LL9{^}^s8SrCQl>5!cv%qLCvrmC3)c!mnbg1T|gywhWU!ywe%O( z=MLT}jPa2yr!SLx{h|8Mv3voEh=-_WPWsK-Y?kf;Xqb&e74!KQ8PWW`iKPLxxeeA= z`Q~T&c7Hz%+P*tuq<*&fop|ZkLYkk|y;((b7s#5QnZl!;nQhG4HHGhvUMOyLhW0_vf<(1;c?;p@)Bgo;oZm< z&BwKxNtfX=ZdoGPV&zp}aZzCAHtf)hed_0i>aCKMVphm% z%&56UeQtiJkYhn$&b$ ze*DT4rA<0ti>t_!e9?V*NWwjXSz{-l+2lm<_0!Uv|LZU5W=$pdxQvjBAgeeNm*V<$ z`tN?!SPYt6aR=nvN3xo#-q^NhNkTg#klB&!>S9-7^M~n{pC}AG16`R}1-2g?+^JCH zF~0>uJ~OizxtrAIZ8f3I%otnHac8u#iJ<)^RNoRCAly-vDCU6CWjrtEm6f{TA;py> z#3^`1>kdsluP^A!Y-eMa<&^-&84qu`=1n8ZGd|ARq<=51Qy>~qj}hp?Df`{cC-JGs zh$H_4ui$4)V!U>f@8hzsO+;OrzYj#}V>;Uuu>D5=&Bi3-MVfHN{$ix`#k>{H*Cjx{ z{1U}C19*8#tbR;m?{nYy;UOKz54vUQNuqWpl$u^Ms+M7KCZv%wqnFd-JjM@fgtyJHg3&kdF44 za|=p!Z>d*F+0hdM(>%ib3 z*v)Y^MQeRZ-Se$ldi%(=_m`wT=;(aOR`Th7Z^79A-Zo(3sV`6>@}G1O0|xx*1|RZb z{c-+CxSt}p9QU4C|8YJy7_Gpew)(~PU-E>``?lP}6K1eZt7+$FS%LtZq*^Kp>mAxE z&0PyeuLecPPD9@IEYpd=R-hMV>1&rZ-Uu%klVl~nhFI>8zPaVtiqU2Rqp^ui4_6A- zm^zIO4=!0STawz{gxg)CPqPBt#FN}btu#?N-w=WY z(q5{5)~`ZWmkIf%@rJH|qV+x}cf5?2J*#q<4_qy@b;U??x@qT$<6RUsRz~7+j>@2v zkAjPuTQLuNwpv*oz0@io@%fvUtmvVlX8>`^zIpccmf07wggC}gFe}a|-y$Y209AUm zf(P}etnGMwfInW3a$EF~iw-L9(o!GNit*%{+4H!bh{C_|eIaR2-a2hVQ#(qp!mp3+ zV9Tb9=%?rwpikCEqo@2@iiKT|OGr?Xo-rA#mO9U<+p_rcor?UU?43U(dvv=c?cw`r z`kT_I>V1jC5j;jABNMAQh3y=t_u0@1lzovzWz>Ftjk4$-wuBgKVhitA0zNObW_f-LiBLGRu`y`@IDfOpiQPQM&$4JDnH$-vvCob@xB05a7^Tr{f0b`} z@eIcQeqSmp%@-EqgN6)mexNS%6wPT*!qJrYB|-wB`qOu%1!DT})&ut$>;0hL(&0c$ ze^k13h<66(u>%2WSLR9#l4oAEofOWJp#3!IHpVEpN@YIx+%^&i@mZ^ET>A%3eZ_J9 zJJl>8^!R(OsICJa|%06jx-3; zY(iQa$f8-VOhMGrt(iSui8}l$v3%oYPFk)#hs}uV)P7pM!>pJcMnt0bZ4FXkdu!1; zZ@EXVCKU0WKC+IZ6jLFw)-REFDM=8P^t&IvK9zdW-ElG_#g zHHrJvI!gwm{(a=3+dw1bwa0TG1~-D`9h%b514-b!nkv1-dLL$)D1p4}_M%tWwtwE< z>2ST&!4bUGY(N&i35CzZ3DPU82B=WfNDHy<4;HM`v^y|VO|dpeVr&LLHy zT(oN3g?2J(eEY)$?sXvFOZPDq zqo7>20#UJW3l}oD00*)dCL|7*xLP@V;c=FK8cK}R8vaE2UZhy8?dAuKe+BmKYE0mH z;@C%lzqtKE*EuOB9N!cg|L(Kg{otpGwL+KR{`Jid3sTQ0jSYCb*F%ZH(q7U<2Rp+V z7MKFLkYUi4w5k%Xm4+kJGrA|z%NwK&(|I6L)MU*}uGsp<`O9QyPu2f$Sz3198MW57 z`r*%cP;I9)7Q~oR-0lJm;+aLLW9S(u1dKEgah3`E(5-4tUfOqRV~#N%BKNKc62{F4 z!T)J-pu`$7HZ$_)>5!ypf|;2u>djC^lR3#BRU34+5|`YlO&^2buvHI=E> zL`LUc^V2fqgUCl@i0=3gj*+dfi=I*xZh**J_GpJ*1x78MSxHmkg}QSY!HB!}Mq#N^ z+gcWD?c6`RE*|ZTYdIj<-GPnK36&(!QF|lZx~5WV*H22DKNGt^%q5q*{NVD$q(zfZ z2>!{E?I{@i71XGxy;(c;RctS$lA=Bksd`6`>zh4L@a=U#hSK^gS#c9;JK-~_lrC%j zc!UZrgMj_=Ppu|3mThDX<~Y8RyeN@j!bzEL_ReM#h|E>%L*ecfu7(@8SEPG9Ru+bY z&I&gz&)8;%ZkLYGO9V^Ww~V#Hce>C}2d-+OKfbhav0=m07+%owPc^Hqemes)Z-2{; zY{_&Z-f?XYc3)E^s-e@k)|01&@OGy<@W|?OLLD8io1XVuilJNOzDuele@naH=;Tf= z!LJ<^bCNR2h=ola>Y+LPQ?ykDPY4~{BE>^*kxgfF{Rx+d21k=_(cGWE^YhjaEo6`t zbM>1SwpR%gyB&X*U3hSb#OgQ0E3FD#5qB)T_4GQ3fzC=v56>XUXh(v>C(~Ln)oAl4xrkJ9xk(bcNPb;tOrsl^+XfLNBs@y<08qA9z znqAKeOXD<>`QuIIoAIJrwl2?d#V$y>*3Z%JC)OJCeBBTulCQz-O`nr@bPnZhwwKp9 zx$sW;caW8A_c!A`B>xnGkxAGO83u>y6GLMDnXN@XF0DLO%R;H7zBs5lp-on)Dhna^ z`QzE%%)d{tB2JwwC>HQ&e7@Ea)w2+L*JXD-e!%eb)^{+jWnqmb%q?5jh1*?YVH(=6 za5tgBvWya6TQ8|6Rc~=?_T5jg-wXnJMq2rkcL%&=w$f zkb%SwHhk7E`c)C#a&M&-gagdwfFKY2FpQy#pK6%dwBGI>*38Nmo%;w-$m-fAL07hF zo_S#-b7{rmdTR`p2Wm;m`s;16o>d}fKV$~_NHU=R0T~U(OgD~bgL*bT3V!L`VRO1( zd-p49>lbr|ru7dJxzuO%fb8CYoxU6pF&%))+8RaFmMU%%!zriCK?s`(O-x*_PR5n= z!~CiFo4CRx%nYWuKwH^ADaP9G_Dw56TPqeu+SXxk8y`cmQTPR#UC~ZVQ|$aX!#4D-(`OGWlZW;Dif!BTg9V!H3&+o z;2)rXl(;MXOKIpM&5+D(b-C{*UC$s860Jdd2Yp?)+&Go3?__#s`?^i()91=?JMoDA zRrqQA29WQ~LNjTOLih85n|GheJk?khcHVy5y#G1PFA@U*p%s?G7byq_)3!xJ4GZ;v zn*=9pReHYJbfKEM?86s)Hck7gi&gbqrq? za|vWLSKZZ+-yjdgsW?s1dV?3vc~B9^nv-c)2bprv6AtmM9&N8X)q?;-@PEZ7gP)Ru z$vc8DXCE!Vxm+SNn-aD0XutAW*CovaJF`N0Xg$FG-K=55psuRIybXw% zE<v5ZJ250h0zaP=WV7H(&9GX7w9r{zT?Jhv53Z*AjWbkUB!YlwdE{p`YGu z`RX z*|``OOE>enq0(lVL6>!TNV3BV)(dWpgRe(eV{;77}6r2c;453IDAl~9w=cncJE$r@khPQ!H2$ln#}^kN*F(ha`lG0#6{^HhYCG30g{M3*_5tJ-K(zd|aZs9@TJkaX9djbjMQ5PN!gl+hL7YJLhqEWpZDgfsA&@aTFN0%Lp|q{80&Wtph=F-8jT}ct&=KV z?YXmhq56b!aF`JI3HWP?q@!t~u?`ghEA+b>4-ls2Pe!`JK+Bpy1>>x}&65qgWuXuF@!=}u5qCpb~xbd=!m-m@E!bgdAm z55@8w_4*c)l4lWFms656=an@tvWta2->z`7;^MA(;rth#SmQH^6SoC4M<1FGjZRH8 z>L1*}xJ0w$cLaQ|cT7V884PYarUhKt3dA%4;zr{V6Jihr+_oJHqj8^2wSd6{KtQ0^ zKDZJo^8{=?&btph9T+__q`l8LxVYI4`zaF6JDMfXET-XvKFkk^EY{hX*p?sI92AEZ z?81FIGiB%AVl-nRNekOTH*s-)7cO`2EJx@EA?rx?^?K6?fpP__7Ti&-Uw(FxBJ7Vz z?oC?Jej=+yO5cA1Sz{8I$C$DIsDPjfg0zJLKU}f@zGgj5EDJke3O#zTP{OSBK(99N zwj}&u;qvhWld=+0-(;fdjPeF6ch0pvryJ^m;Txm(#V}bfFI5Jrv+s`k*%T=cJcUNT zaPISU_bi<~W+X<5rqp9r`|v%rvjXKL7-O;)!@9V!KnoE`#hVgj-M|0Zv3aSFVi3}Th#9$GAVrlu0W_7c2)Od;)4Rhx|mxHu`{qOEc7$4^*g8#Q3 zjaR?xK(0qoQ=UEt{?lgEkMNspwOXmbVr7Ezsi7xlu6>430M-zOu;NOO!$bewH5?qIocG_1`y(rYLRF7lLA zAH6{O@}s=2KQK46a`q8?TcWq?`1bDa$)ejp>O=L?v<*;HkK?5Zg=Fc{rUrZH`X?Nn?O!Y{8RRH<2hmn8 zYHG7$Yvj^(?~Vu>;%)u$@%Mev8lwd>P4C;d|EXWFHm0_DH1=AJDOn^pr*D5-xdf7l5DjRI(y+tC~qykj+fim() zIb)&Lu}X-sn&1Qd_W(7ZY64mV+Hoz8W;r#i@AUy!AvvAbB7f5;q8rnhZB_|cjvc4l z6_Y*pxuBQ*WcbC!5cS^z?h}mrylEqTs>xbDx;ZqH2|$=;4OZz?Y z0TsXb(vwb(TCNjZdGG;yLnq z>Npr(`X=8eD&*;4+o92^k#Jp^}MrXv+>nOgVdSuO2q?7*57+3&#$Pe zKcnmCdDHVL`5dDGqtaOK*;W0gT17!s5xcS!(S9+fT3@5SWLR#FPOB5ntO6w@W2C~n zVAV0j@>{*FAy}ClRpWB{Q%X@_dV;XxV85TL$j+v_kv8z=MU`+Jo{zXF#|TIMQ{n@} z{T!_y!_=@&3u}~hu6fcq>HB8uPMo^K<=GHE;XBgbBE4)GD??Z3_jG@nl)w!>U5fxi zH&O9sI$Ba@VQ1Iya-g+$xpKv?3YU$OiB}v=#vjoT1`-voU5IJP;e3^YpAFa>>ffJ> zPj|ROVSmIs(z6viCOCV`}mrDP5fna-8Y&i{#QkMiFJNS{LQB%nzgnncak!bh$9p0mci>qcxZBkS_z3yHo2U9s}& z>{%^hBc8(og`1-z?KCS!hP*LRa1;-{=R#5sUal?Fe%2udaG;J`8u74zsWWACPsmD( zT9k@(dvZJu+dRu9>n~A_&f7>U+FpH_;hOr^iSuZ@Jn%;(cP$Yyr;D}SmZgvz;@Yg2 z^x&$HR(67JYo?slwAp-l1Gc1pw;+hZ`6pr{wJgL237s69<1kz=>^+y(o;6RT=wEz< zr;ML>j2I91-X^;?MGIQt`m$3Qw=l-_%2!PI3p7x7TZE_bGZo#Abp2#UW#$h0%&tWx zrRh|hnsVk)zgBX1m9)2g3yG-L(!!l%5? zdux34yC8QwluME(;M{cKH+G&jJ`^bzjarTlK4keqy8SoT?68v21(ImNE?+{((pD#$ zM*YMLga;M&bg^fOHeVfxOl2xD_6FVQ1q>oVQtH2WDpE-q3-UB)1~+G~X*Welc_^hz zqb?yuZ!*p3o|}GMHDBT)L8@Te6X*NCQ&vhD5`|R${{*&Qs4j zN%*(5G+dT6Jm4BQO-bJHL`_aMY~!IO&JWG1Lt(>GU z!57+zo+20y?ty{1ArKq>aKt1-*Z#Fg`~Y(A#uvYmWDdl_@iGzRh6)Inm4hIK#RBH= z4Ta_j#uS-?9ICGzhC^Ci|#bb!{^tJ4-r`sOM4pVpD8 z^;*?;&2Zjp>)nXGtMFKK^>?&_NLp#f%lr zQs&@mbPl&{im6z)vA}6e@-%{0ZCq^ALIzl-XsHzDRM#)daI3q&&?RF7u+mB+mj{ta z^yyAxjBF9cuBoZ!noFA#+DXdX)gD*1oqBh4rV|-}veCAeUFWt1g27dHau$|0N`D{w z1i$&!g-B1tnJG7E0#O-j#+uc6NR)NB%(K5JG(RsK=ral@&7hC@DaE9NN+R#k zE{E1(K(}WZIIT5u^AU%1x-}6|m!D@zm%<>PV}6LOux*0`zgI4!Gz>b)T2&nR-{#jn zaz9T0SR}f4vN9wC1U0rj-a|WtBo6i}h75yUjcwC9F&_zjsE?11qb!ZxH1;I2v)|lx zyacxPz%KEJY8E(6YF4K+M?188o^ePU?N*B8aEudIi)d5sFZT6;OCy%d2! zVjZWrqrudS*`HI6$Wn;$T}bv!RWPl1D9#~~0$7~vc|*tk3vI22IQm7Ri6ohcz}Z_^ z79!QLJLmWLnRTeuarI?5pv*<-3DMQTA1}P&3v3;zVfdQ2LG^C#g~EbBd{#5rF-0BB zRsF+(OE1|w`IA94GbL?6k0g42lSu++0fL&ebnj*+XoUqI5r~$b6>koNM{DwhT&_dZnU%MI9vwezQ?ag|rK)d8zuG z)Uw9|jmE2}$_!#;5?Tot2#R6xScTv-7q(Meu++ZuEQ{p^DtN~F_GA5m8# z2fYMsx+qHJ4a^ObP@$GiQd_W?FJIV0fNOFC4b)qbOEtckX1CcjD-46C6Q{@UuC|j4 z&=2Vgzum0>a}+oH%rBf3fw^A1kWx&WPL<;$GFfRJdM-{>ld;g4<1x00x}7QsimwSa z;oa$88WT8*~d?GVdX0r%SZ{Qlw<1BS1Pjd6kIePIU)snAM($vEw9sHI1kDx=< zv4lV)^z6Oq0N?9@`+z5Cg~HJK_!#LDEqXeV_fuT)z|OqUQu@tAGWNMdZ)?q!kbi6o z{LO0ek1XkqgTy)5;r(rzP&E+WP@|yuq$Lw$ez?*@h#=tVPpIuH6C5J{INk z!Qtuq!DmdUJVv^{F3ym4{}{tAiqR0Ekc$QB`|_Kelc(X$^EGTz@k!DaSxYG$mC(O4 zOvRx$OQ}~eime3an@ZmHV}TrtRw!3@8)NZhZI2HO_$@A$@uu0>DA=&2CzN!_rTx&! zqq|_Uj%_+YzI4*An;GKsBea04OKA?2PZdvVPk+|NpKj8g98RIUEo7E27=TY#YlLG& zJ_(-p^MpUY*js@gOIo93y)ElwzFq;2g8dF3XSxZk-gZg0f(x|@N3WmmoS$r5aV9rk zEQ)^ho_Wgl8>Glfc@?hs@x7jv)i5fY$Y&5D{uX}c476cD|F{@h!dt2{IPQC&AMW1o z%QJpeon##Bm_+o~T&5_Y(0Sb9k_e*D*O@I>^5sVGVP0bGshh9~V-mGK zogEwf1FCNquL4d`rg?Pw39!)u|L`*;$-JLYA-$0zz5nmK5b|AZ`9?j)gI`Z^KXS>N z`o$njb&=LqWDC6~oFSUFL`%njm<@(C2`aL~lf1_IMV*Xz?7h3Qxt<&W=+)?N@ho!_ z0#r*zc$`b@^OUuORl^}mnbM~~;l`QU^}yv^zXS+j@iRaA0LxBc{`u?U^iePI8)#m; zbVqjP-l{hQ)@*XJnvvUba>zE!;CC`c^rISdBXSG9zr6_N4-UG^JrWd^?(p?E?>w3OyJ1kK8H#a}OI&#$%SW3Ry2)MgbJ2}F+ojwHO4A~Z1^3ku4HJ==Cl zV~UwBxy$jD4hH3<8skl=&j@4f_)ayt_b%Ny+B#v_bn`0+r-sFz=K2NOp55&^?@{!w zc?Th%5p0`t;!jb>zgG37GLJ%&0Di1VxlIfy|F|X*=f69H5&l7y(@q-S9}BYy(@Yv4 zn=mh?`3L;(mYtmt)u}x{#Pw}fvBKdw0%(&XMt3femEIY21+6$Kf%x<9Hay&e>(A#b zj*Z4l?*tUy=QJJHGnA0l8H|ndgh$;d2YYA)(KUJYncm8srwz~EOHgIyL zguEfX=`|jNdg4_S1jyPIG=mOTYlOA4be)Au!Tn$|-fR(j~!N zE+l|h9RvCa)E%{i{mPcQvfWLaYDYhIu{im1f{CB3p9EuAe|bqev`Lh`d3jtXLAb9r^te=^n)pcKS3jJw2B zP|W!#QqN#7-niN(TpA@tDR|Lf?nNH2`czXhJ_+_nWGlxQ$dHvHaiE&d!r9hAH@O-l zY=M7UpVJ9nSXAralfFpZ9b6DN-&$F&xJ|GT2(lI0swOBFH6$>m5s_x3wIh#(R}Ca% zTR!gP;;(`p;3rRuCX{Wacb2xBSO;S0fQ&&3@I}epbC^_n#*1}|bE+-+hmG+e8~dqo z+J()#w7@%mSgez`jZm+mKlGXq@w{c)ViHVu&_V>^;AuHux{>!Tqz&G0dpptYP2nWH zyaKOakN``{l#Wo4eLu(lY>&KPkC()GgD6_+1d zS)i~E$@mU>0%T30&vGuIfT4iK*cNY7hENJnK8lqHgBhuTH7XZY(>q_Z^kCt}6Ktk) zTyTMS%@6J&o4q}XyRJ4mMu*S-sNqG;m#a@+4!X|toCjy|eDR@-SF7Cdj!&ePkxQ(! z38p^PF=|pYau7OJ?;93U1EC=X0`9dz%$tGR#63pm+SO1&d zgVJPt%35SNRZ9JM%*IcDzD}H!;xHT(w5(!!a+-;sm%?~8#~mJH+3e0mf>}H0YQ~#Z z+2+`q6RYBvaadRO&3OEU@K)3fKWzq2VW=;Ct0n5FPwqm2FF*f8db!s&ZmQ;YI1J4U`X?Z^Z6! zw*;BSI5le{!)MFg^0;)|i7p(>y*nwNbQH9VKY(Qo=OHPvnaMpFg-8ptO-Nc<6z`5! z4T&jyN!=O_Cb_<-iM`zr3YNSN5Z9;rzGwX1GYSQ4`Whbn^~g=dUhfs;?!s!ZI>8$C zZOa&%Ll;Z5JWY!f(Q#bA^MtiiO)SXE!-~;FbCPg%t^e7$-JpffX3J~zhM{@1em6Ce znxjZ#R14{gI`T!mR|k?8^gsj4kh~lkHoO^{qfw_veP2DHsB5CE49w>7Yo3lpZze@u z@nm~-%BJNEgngfJ7V zuJ3X$U+q!`2A$hUbp{D$wJPGtbgALCoEc88G*5uMw~q_Qw@2ElP&oN3?U@6p)cl{N z#u65+D__b5az-9qBSfS{6|)&|JMf|_w%h|K1FDIrRLXM6Dhk&H4w=?Ofux|}ntL|= zQxtNk}=u@W=aZAh2~E31P1O zD1aC^Mtz9}O)r;B`5VXz-G|V3vK7b)8G-}EZ1`#(SnpbOJ&9@e@G38bjWOkSFByDU zl!0MJI$~D-F9L3zRpYg2Vf7hPC5%6mONIjz{&PskLvz3_=W8IJI)@7$?Dk~o7M$Y# z?b$jS1f?orwxTQLAw)XlGS3Wv0zkD6Gh8U5UBKIm19GoM4*1WDD2jt;k5}ws#vXgd z<>AV&x-uytVY*Ke(`JrW@L+6gFDq)$zStyM!_YTe;PX&n)I1b*7dDMPukM#F93i4t z#I*h>so2`SD5>d?U?2R$t=!xY-GTrXaLNfwdR(XwK|>G#4bV8=&iW$9+o!7bIG6`W zN`;Gy8L{y=-C@M@^q_sCQa~%Wl*qQ8VrjmzMv3^75lmm3z%W(3mcz+3azi`h;g?gQ2aN8h1x8Snt2$Xa$ z)whRN@CPcJaMvpPel+^U{k&%$4~ShkgOC^DKzvAT@H2pwQ?5d5ELZWTKm7HP8L(d9 zk-WKh`jR(NTTr&5OLucd~cxCnMJ4XVZ>q8D1S&#II|~ zFR91aF-fG-V)IF)u3=UAA2bm0_o2b+*%BLMR;)ev+}!3p4`Z&pLIL$W;0IJK&Nw=g zhr^l>=%yPt%y$Si>_JmD{>@n&Gj z1)Db0KVE#RV8ycd)}4+K17o6F&r6Q^RYVfzqPRQI9vK zZU+B`blTae_ut^g|LX;t%)tmTIK|ggIvhaHrHwh>?}#SPl@wB-Q}K_&s-ZCb_o0;@ zasv=|Fs4J%db_c#N0Poc(Ax(Cm?TLKL(3i7++BN4Lxq>sFVoIDJic#z{C;jO(WbuR&Hci1L942@ zPx)!pv%yrzu1K;c72J*k3(C1v)u#nUdYQdciK^pq_oZxf#7^u%(I#xdaVzrwGjj<2 z;M(MQ*K%W>RC%=Y$_~@Ydi_mbnHdclw}Es})(O^>A2)Vz7QV8F2lO zIF(|FzN*foLMH%zK1#JgT`1Z5Ja2^`^2Pe?3o5ex;v?Josdx@284g+6f-Vl{?=8NC zR;GcBC7z&xJ&FdoD=FSpoYYNQsh!sA3@wAyiPIH~RFd-`)5CS2^6)W! z?8tmTw>CS>aKD&iQAI}GjK&6ZB&7r!39per*-IFt)@7)da=>g18Y5cl-THX9!B+)5qdC?X0pPdzruOQRm@Uhe7dw^C+NaUh&9j(b|cRpMSSTk^rvmJ{E`w;kYaA zo@dZ8SVgpB!7N5z?nmImEUHZ3GeD^NVfiP5Kvcudq1K9;-~2z%x{E?aXZk(!31vAD zC1wbzm|ltun><}yUfhaQ902x+j}0GI?H`CZI4A6gzM-(DpR@S&pBVfA=DpW4WWb0f z44XhQJSS!)@x6k2j={6S02aQbd8Y%`G0Ir(sR?ww(|8^QODqRI(DTVR{T+HO;gz}l zB9lk7f#ehc4k*^s7D`|uXkVmp+pb^8Cm!cUhmmY!On;f}x34RhY z`|Csiv<@<4#Q%WlU~R^n6?Y`ohgwf%ri7J&hJ_hfgAFf$_hN6JBX9&~c;D=0P}FpG zwLf#wlm-eP(W*HsCu(kIep%QvqLDHKSI-j3h8)3!u>cG+(*wV#Ai?_=r$$iYG{D1h zCqp#nU=_gUf#<=0VJ>JfFXi$X65z^^pgO|~h`D%eDK1o=@x6D9s~GDYsy=4r(5lkF zJk(hHgsQJ313tK>9?!9oQ-nC5Ic{H7?$r%RwX&1LIN*oaF|6dDF`(qyNX8h3aeW zaR014+t93%mk?LZC=3@U=Y#XdLh~{qFvqv`NcYgQVKuInb5im>2n|lO^-C7jCGh8n zFAm$o*9jMs+Rpwn7Yiw@of$KWy)*gmm#=S+tPN8ArkWy;`ha{XNnKuF?SCw1w}x=7 z2Fs&LA!+T=DM#h;G`@xw-gg(iw&W;$sSKIJrUTnPr;gp`JlVQkCttt4?)%db_xP}Z zqKz886S!39ZQyM%O$>Q-4Ou2G{%_=12S43eQqS<<0If$jXuMBQl-nQfdhfhJ#sd^5 z3uurq0a+0LQcW*+*Iw`Z#F7|Tl(wJV#oB*9(q_@LK!UMEvZ-a_+f=liRdHqH5E)Eq z*D!?Un6k=J8raMCy7h>GXIUD;y{29eaKf9@67($!xiC%k`WYDICi!qdTyDqlnQKXI z1&pYxPkVbiIBv)~5j5TLzL_vK@+paAmB)ACfAA^MX`FRQ{=W$gVgj?^UUP z6E&Gx{g{&Ug_-5RMxOu@?v>w-2mbTlCuW}rp zRlD=1JWL#UU%HE{^|uubgGZt0H;30rA<&Uk4ab1OpV!tnu9B~*~XOaICoA*Y*)Sx*w^l8Od5 zhG;KgTGZhG-dr(6bw(TOJ)W(V#4<#x1KzBynPN3zu6_KQ(BL2GLj(}Utq(uyCA3ve zt2yHFriK@duLd1(dsB}W^&biB)-{BGXg=!73}4^qbzACnn#bM+S4mJQ_sQ|3GUHMO zYUdcHJ}~22p#lsj>PMvPH7}#+I4aeagl?MlM0 zaDJQsW-%1yc|nTgb5SY9Ha$eArQ=%NN?ZUZ6C?cV^Vph|1h;tmwKrQrN9&p;t^4$9 zUy@Nshsf;IE{y|G`+vSZ#oyq}nA^H+6KY3IKNPhvF5VS|x5GT8DVhd07f*sVMNnEz zrN_RG+791=kK6T!M@GaOz9p>;N|GgWmeTl)c;2LV8z!fl@ka9y#iqdq&4u;}e?;_G z462qRoJW@kFV7MEsib2+QCXjahE;H3#F&vJ4-?zxulOqIL?hlWDuzU|!MD?Es~H{w zpzpH91tXMvUVobP?~K#q5pe^Lht{<`Ol@Ger^j(lT#$~etfJW<0*0CXQVDT zo|IL)Pk`;Vd56Bl{euhrhNyeH=)(IThGx@ksWJ|V*1h_x!<*aBl_YbO3S1ghvLL~k zOzhS{eUC(y+A0bNb$(-Hb)GAO<=_+u+p5BKkx0kgKI3A=J^#~%YuTz?@qKWL2~3tFs- z1i8-kgT0mEh)57tpG~OKRG`>g&n4MXbl`k;Sps^Az&GgwaFXiYn2r_n1l&1ol$8+z| z#V)s?;yORs?TPYGq9aYtYGf`c`RMn74>iooS zn{LFfK;-l@Kar=~9`MFRca9r*oy~!tksyu*`x) zRgkU)vB`F5VM+_tQl)tjU{d?fzyAL_KUe;GG4L5g>QW|(-2+)Y9%|9Fe_Lv?a(fa; zpfpxD44G+C zNhqa`eoeY8Sf@=N$JkL)kf)Cu_tVquP5L+jtB457pg>_eD9l-l=cKgf`Q`p=D%!mf zo=XE@RX?1-^N=KL<*4Iuo8mlaY2^J@vvPSnUL5TF+NlLEe4@AMcx=2(T$qGI&d%0e zm-3Bj*P9L+D3kO19~8Y_YXr^D95fYci<}*4-z!1$^??^B3%mZ+KiwDd>SJ5d`hFFI zkYE26ZjiI@JF=`7vgm1t`R*J|XaX5+VL-(B%`Wuncy$nP!OH8%*AJfE$ZP zZwEOT#GlTmq7J2s4IWk_2+NU26rmWh;(Mpdr@mN|c3zg#Kcl;BnjL2ac(l-iB*%Nb zNe@UM(f*CEvmJuM`CZEF3vsSomPCmmjfC(e4LrsZvn=cq>*LmmU7Jy8%emz8m5sSS zu7Bg-j293bl8Kl6N9X5Y@~-1eJ2OHBJGJpm8|ji;a|C}NVf{@S4&2WiZ<2ybC=34P z7s7=M^3o3ez!-2%eAEs3Knd)b|0${6Xb<0ba8bRw1O-t3a~k-p{|}_MASPg`QF9W= zIQEW>u`^EnA7dQA0;b4VpN+Aet>d}nydp2s6ORQ_el@kD!is}VDvYaL1IfOc4M22h z%Y($nPoOO=omndv9OxyPLeJoll)IvpZ00vc?hi)~$}826WFtIPE5)Vf7El1D0OV ze}kd<%TvT#Hm*W$^Q;I%U^#X1(pKY(2AO~VLFm#vbEM5jV?p^--?LCH{(YY^jNQES z9jbZx7f&sQ!@3+w0f^`0!+yelK5x}NQMQ_3oRk7)0lp3Y_;!O1ZjoU)y!sCikA6+% zC-4`q{vN#MRQD1Dt+}7T=;?B);VURwRd@pb;N}m=TOP}4hQG$3@eKp?9}enXvT*&6G21`JMEKU9mQmZdEb9evF8sfn6NS7JA9YmrJ zKz=?0jI^7VJhy~3u{q$Xx1Gf@re);Zb|94+a3tx`d-2a;PIG4CeiHv-1G)Pma+*N< zB6|r=>8hfJ4Bt1*tQbKeSF$o{Bqbf(rd0MCW@oGb|JQs$rD+wQsZxo5GlR}r?}$IR ze~{;2Ki9siJ9zjHv|#fqbQ#oe-LTp>Y%IWkrbwlR&r8u#Vph&-6@(!@3~<+2*mk9S zz53#Ns%E1D*hcbSxKaoOB4#uqqvrYk|MYd`@ldw!UW9C^WQ))yS+k8wM1|g@C`(M1 z$u#yio7LTmPpoN3^SIoghCk8!ptz)5@H&oge08%8Qy;9oX_VR|CpK2%=KLN zbzjT(`d;@u;{raV)13gm7{0Hu-Qy*hq9+C~HX zfF}@W%$Cz&9Bxc{#t+h77ca4N`4B7V*`^3o<2i579e@ec8DS111=SnZ>IaLvXDT|f z)@MkSg~q<`n9uax#RGWYNB9Q>KO5*PEIyvT0`lx^*!2)W{Li2NLq%5lh1YnhBf@qJ zv}%kt@Z$8ox!2{aHp=a&EVL6pF;JsV9ho~W@1dz8`=ws1u5^dV> z!^H+<>zMayvuciE6Tr?qG>OgK`y+`1#?#!2FV&xuZg8ThzPczbqjgGMDxs`hnE)j72hu`nW89#buas0h5 zpVICyABu2}qWjCx3fN0bp^oDm5>CjJR)dbf+&2Qtq}smwD1t9b1tdt|>|-K-m(8_3 zzIw{I`l8Zz<&swt@os}V4gg)T%n}KYE0Fq@0_5_}RgZ;vcy(krBB4{1@M~ov4l__7 zb^V<&`hFDs%g4m-9_^* z27OX!zaC6dyxyP6UUPK`^cts1~To zbj=2ePLwk8%VSahyvt5s{8A_BY@F;sKZNVL1$!x#-MRB65R}DzPTBqQ3hv;NI$wQ96T zYq|YVve%Yko5lmiF_rE{(; z1Y7OC>R}3|ikbx?gLZ9}T4^YIt)CwZty{k28B?yR@ad}53xap6Il`qe5r=*2Bcc+W z$IL%)K@f29kW7(@(sS_>ya5ub!R8OF;hY{TNhl7762`@HbY(0`vg2B{_#w|(SF0*X zm#gihg^GB_B%GB>!HpznOFEa*cx7CWp2U4=zu;JC-I^!tivc|ReKp0SUEK`@wR*PpK)u$g#d1xvthV6zHE?+=l_AOBtj z!rlclw|^#~dI;)5z{`L&#Ja!+_CPg7YbE#8k?3Z~m1X`#ikgG(WXVbr_|vs?TKbHk#Y`~N`7#5L`_KkH>-{7>e7mt%og)>Y0fP0C8ou{x5K+V+aB zBUhSU&qSUWzS4B)5Xn9RWy|??N*f>Ei4UYM5knOxe{0v4jmtULIBhfyp6&s!yWto1 z&8DUV4AivVM^#-S4#=c~{K@j$2=|;+F{SEt7>YMXz7`kJklSFY&TnkWp^EC3K{W90;Tz7(iH@xYx> zJzdb!0W_gMfgt$5=@(TM#jUXkI@oE%_C!Nx`$VT(oMZLs6d19%D{JsAQa0woN%f)QBLV}_b3?P;i(NvbMtg#|2_qHStEmiX{}91fgGA85=fDHqid zdNR=Ht#QKkilMCW;HAzE724pdyjKVbj!GnVxO079FxS{LTlTgzwy71hVaB7QH%BM1 zQuVv#|!o5qT{7Q5wj|nvH^*S(A_D*rHX#lCs6#D z^g9%*bl+K~h6h#N;OBQ;#AU!@FQ1Kcg@sD(YO75a3N;(!YcXA@Z%{KgTu_yJz_90i zIiqRx`)cJ8HYHw)-(vpq%dFZtDYxLp{?Uxkc{u@(jH-wdHnd(kX5i&%1&=EGdp6~s zril%JosJ0aziBNukaoDEFCGlD zhh`2g`+Hc9dXa32 zQBdVVLQo2|eGkaeOT4Yrdo5^wN-FrgiW)l$wqmDr;LVO(ePxzX7{JTzBX6J};%D>Z z+e-_~VM%*&Nxp%|`m4V4z8rGFCQW5iP7~>t&yAP#yy)InKQewsxkSCG%AGO?zbLezn^JU|auF`Ch8>CEpl#hG__>BX>AaBCL@1Yh#XT-Idq2lz!V0AjW!vSrLL1JH`=4P*>47k5+@%z@(SXoa%~I{I(L0|FQi%zFw>##h zX^}6_Wbc?MqC-U72C49{B=rT@I(BE+eU7Y-mLcG8Th>*1LXh@XG?x|6dDtw+b#y;pRC+ownO=85Pe^R+GAwLU|> z1`||KzC$!-gOOzsG$hq4h$$RDTu7;=aNWfyNtCV(!5@SgUL#LDJ63qVqayqC?$x;j_$4d*Rg&qev#X$Ot0-C!&Ke0rbDW&8=2|AC;LfFqlJbrId zUlLVhKXBLPq!+|}UIrG!?UO7TTRIG;gU41&f)gfS+Q@B#6WB9p zt*8A&D3yNh!FCO6@@x{oB@?|meEUCDFJMsYmo=x~dR^C8Y{i!@luC$XPH^C2QG|_k zjg~0TRQ%HJ36pHI95l!Pj>ba^2VvbbMvrD7rk-HX%{lG(a?D!5Bj5fYjG?X(*HufWBT zaxV8HZ)9@mcNBAvqVU`p)p^TpRH`b=!%cGIu_c1N;~{T2A|(z1IUY>fJoDKxI?EGp znSUNKv}%^3vS(D3#}z!*e|C^LB+vcuATprtU)>;Iw7Ibt4S^*C=Kd1O-mbW5eei@O zK_r3{7!Lvf0QhznMMCJ`3=1|`AU`X%c;NbH2cTk)TfVWQ`$hR5Qcg4;?SFEodM&o; z`suW)h*{Eog_&#pKZg?v%f8irq111Ol_AyR`sDFjpYZTCtI-9zi!=p2x4R}Ik;4t1 zY$*Vi5P51{yiwMcFU=<2L^qPaOT)mbW|s7yYEGc6U8J1o4c^&)BpKq#?bQz zhdII@HtA$`!ZK#3eRh>N&C8t;$_l9O{^~JQMQ+M?_t^NErtxO@{-5T6GGv^dQp06x zrbe`#M-~^ZIEyncZ73evet4VZL(>3=Kw#*Ig2sJw1E8E~*3~h)e_NV3&3N4M!(8Fp z%t8pbLLX65P9Przo|C_v)bGjb)V}ZsK01QSfEGf-55Bk78uVpQlK_2&lgGjcJQx`9 zJ0O>Zg`9kImpH%Hd6T)F-N=z}qnEF>aqbHrMItCm_|YmQUYnAjV>K@BP|<_5OiavQ zgp$serbCOF?1S^Cw?u<_Q&11a;`%rD`-0)jPb*gRsi3|DO1?7(L>zIw^-Ub&TrHJZmL8LGBEA#E37Tulngvd`bZJ3kvk+Q48 zaC!wD85|vW6o|i8n{@B{X$k7VG2)#GAL+0@Gb($<(QYw0-EScVxd!@TF*mQ(7O|0u z_S!Inf5y-rgtm|0JN7{9?r}-n@|2GqEu3!i)aB%;-)gzxT-fvjH!ZHVQaqo-kq$6Y z$tf0Em5g5O39MCCwX8fwvl_1dJMFG@34-QzoxJ8S+RsfZ?K9@s?tq^gWnP;`msIz! ztFpg>p7Fbr3EL#N`CZG)ID-4I&Et&I~N+w9u#bKDE1Y=iw1Zay*?w9u0P zX~NuUEu)k2G0Ft6m3HMlYJl@|L6M$` zSHTtnH&T_m_6!Q2gxyk;uFw>uSZu?VbiNyl#!QapOnD0iXfE4BwEC9hfJURR*>r#m zGpp7#(#1{w*2k7IAW0LTGb}jdH!sJCslrG857o~6s~RA~U!Sga9jTriGyAs8A~G%2 zFtzDb19>6=jt|Q{2+@`|zt(|El|}4mKEJlLlbZ|t>yMOF%rHrdPST+(Rle}%=ba*? zMyM8&79zau+m1#3o{9YDr0Z}vPR$$r$|p0|DME|+)hmbgJUe`W+WkWp@w+jLB+~iF z>$Sm68bTtA>jGXY@)V16fUG^PUBd1#b4M`+f|J&(yRt1?O2*1(8#PXVTuiHJDLGBk z*fI!%*d|gefKaFtFiQ+*3v}2XXY?+&U8F~opGLRTi&?`uLaUAY9F$o*q|ebtdqWBsaAuyq*imzudeq# zrx5U~$bhd3c zSXsoe;Gh4Lo&(y5@J>sgutX+6kzx03{EbB3UWDdy2L=14XU#dgUPu|maDW=1v%DNI z=l5ru3NaCmu!T>PJ8Bk^7xh4<7HH-orzaSF0IU1tW=$rM*;8f1cQ; z&^gZj@f&i`Xby)XT=$P@Vo~zZ+N=77^InW*`ggDA&TWDIKczrJpjmh`BgV*gUhegc zI<cD0u01nL%r_PyWox1xLA&LNV(4Thb zTwFkg&EOTamxv#P1CA#LN0p2z6UPC`#x~a_V_A6cM}K&Y!5J12PVRE+bvA0l4+?IW zaJqtKyLB6a_B9Ni*e5^hxfR2-tXM|iZTHCc1o=wW$`92zZEA(=x@3Llm+fb(+eH?& zwd*c^&A9SmPT$(3p+n_>o3pJ0A@c{ZNNBQO8^84NsMxlX=<{P;P}?*TeXXpu>D^lMT|%c z?Aa>>9a|f}dLS{80g6*Hzu|S|Lyiiaa(h0Q0T0}lJ7W+R>_4?Ocb)UMH?k0$1GhgW0o`wZ@F&N_FlZX!Bo~%C0}Z zQYv?`r__k*vF(N=t_b^VT0dmRyZqH!KKx%+&fK(=efVhi-ES}MZ^KWSr6dL-Mh3J` z8llG)%?~3j#HYm$mklZBrHW}QBP3eAaFg+LqZpFs%IhpOR~A7!b4n2swDu@7w$&amS2;-MKlE3b0$10xnm!x88%>k z&g;J-V>{IjLzEG6cfi5uZo$sW5&m!Es?zVAAr8ME*C@UFq@R`3O#V|P$9?Q4JUar_ zXEJKOH;(2oe*W`J;1C2cFH#&@N9yHPSrhot%T`WpOM3+8V$nNYV$pNIY(M3AUCa6p z)p;yNFLgv%oWp2RO!#E%O=LFa0l%TJII*t$lCnD9b)=m&%bMHoiaK&l;hTp#etfmw z$o3Iu4dOFLfVkj1kf{sW0ZQflusR~jZHrcg)*i70rcOvxXfSe3+%3>R*HEe95TDx- zD3p#!jq$+u_d*LLywVwd0o$}11W{GkX->No($C5mwOKXg z#e~I3kx3$`AzB>pH)Cpko<=iGKhB*(l*Nbx<3*-5w`7epLp(JLui|fm8iFlK@HbKB zr7hNZzV8mK%`P~Y%LO$}Ko!*7vD*N_E-7!wb%s2vxC?RB9&^v2X)wea@z8`YsX?d@ zh8L7!sSmaC`oH#-%f`PZ`Xz3Aj&(*luC8g!h_#%4pzWeLlet*qI!!QvPwVr84w6@TJ5)p?jV#qF4WJeax~e38{5PSsM$h$j54R^VCctio9c?|+Gad~6 zL3_CT@IU(dVi>ysbS@DhJ)MgO^L|PEy{Db9=n{XWB*Qk#1&4BU7|N8m8c{<@2Ks6) zn{HAikd+M_R=bf?a&HLub?p8F;^MR!39G;icv{sFWTMN}vQn#~r^-%j9uobFxH&FBvbgkF>yMF|17Si*Jr&YpJ_?qrcPFg>?p7~wBm zDCuo!g5*qYdgHD}{F){u34$O?>+c}2vIRd1Nse?u$-B-wr8LVIK}RjNDd6Q%1TFK@ zcbvW^bNO9ctT_CW<$u?}lAQ*Qu&U$rDGpKRofJjC9=u`E)M$#Nt+T{>Ahb2hDxBQf z#cGK6Q6+ADe65}|`7dXVLMry;LtLaDHyGC$s0@L@LVeNe*Q82AVZKjf&Td zFnxiY+HJo0AHuvlnyi; z8fX(abgVLL#`%M-SPL?UzGp&)|90@-0fO0VN7Zm41;n{e9~<$%Cl7UfYO(=?6;SHf zjuB%PH`jVYTL6jcbY7#gu_hM2I1J}yO#?yNCplbRQis645rygV5`lr6p^d%x$OjS+Pf7*6Jko zt)^TweJ19AjvPAht{Jiq-o=Tqx~mo*n&#h_9`5!v)$J!RhP#$BJ+nfGtR3=9+8I+nl>0+~Lg z9sMvJ#N_WQ@EITTocz6$v$BAzkaAJa*!Lq-tU1I%;*KSGK<_XT{=iRQy`mn%XPL%MHa#AX#AzSIZC#Kw zP2OAgZbE>H^IEF{7#|dgBvl1gd$APdAv9^@c%=P1#YB=lHS(w72}o+>{Xq~qIuUCGWNVgtDSdmx3B zaAGcqe@ufKcm1DUq}aE&$*5n;uV@h)cPVr-S@S1h>fiW#kiB%Y7qpPzG+Hn9R~_I} z?_6E_pqp;2ZBVfElTmR6BNd}b(%kmy_pzw6>38!|18y^ZReXt1SRC4twq-|<&Y+Ga ziT>s{>!E_+ph5mpYh#z{+9`16gb*q9%6HUpd#8+Sv_QcIhN-*2e0{Ko(Y$e!!nDM% zE_0-f?yKk8$_n5g+-FGo^0H75)@5+60K$^N$5n1!YUx9@M_ejN`M{T@;Sz>6_>M8nC z;AqSEqBkvcHsYJ?n;Rpu)BjmCl(bz2vZodKs%PadG6c!i(qoRR!%Hy{o7Urdz8!<$ zM|}T1g-*d9K*Dvn(Z826#YUuW1Qi3GX^R7g{t^GSk-2``24p<=n$P7;eRlW9=A|y~ zlD}iaGTAkr<;%fQKG_&eQjgUXi{ktv0H#&ry*hphn8thG9p_!e?PBb&xzUPg9B`D@ z6s>t<@{H_k!gxd*#1z?n)ZB;5T9K%>{g|ytckg^EU-l;ZThF&4W6Vl)8!su)a~crCqKyhl>FK4--( zF{!-QEajv;_Dr-n^0+)`2ugx(I5J#@BWZ$5u_&omFBoAvXxBSTj?;~@syLCFl^n&0 zaN2TIb}{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://127.0.0.1:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: 123456\n url: jdbc:mysql://127.0.0.1:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://127.0.0.1:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://127.0.0.1:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://127.0.0.1:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', '52578f112a386671748b3466a02c9cf2', '2023-03-11 06:45:27', '2023-04-18 10:29:16', 'nacos', '0:0:0:0:0:0:0:1', '', '', '试例模块', '', '', 'yaml', '', NULL); +INSERT INTO `config_info` VALUES (38, 'yanzhu-rocketmq-dev.yml', 'DEFAULT_GROUP', '# spring配置\nspring: \n redis:\n host: localhost\n port: 6379\n # password: \n datasource: \n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://127.0.0.1:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n\nsuning:\n rocketmq:\n # 生产者的组名\n producer:\n #是否开启自动配置\n isEnable: true\n # 发送同一类消息的设置为同一个group,保证唯一\n groupName: elink-service-message-producer\n # 消息最大长度 默认1024*4(4M)\n maxMessageSize: 4096\n # 发送消息超时时间,默认3000\n sendMsgTimeout: 3000\n # 发送消息失败重试次数,默认2\n retryTimesWhenSendFailed: 3\n group: produce-group\n # NameServer地址\n # name-server: 110.42.150.117:9876\n # 消费者的组名\n conumer:\n #是否开启自动配置\n isEnable: true\n # 官方建议:确保同一组中的每个消费者订阅相同的主题。\n groupName: elink-service-message-consumer\n # groupName: elink-service-message-producer\n group: conumer-group\n consumeThreadMin: 20\n consumeThreadMax: 64\n # 设置一次消费消息的条数,默认为1条\n consumeMessageBatchMaxSize: 1\n # NameServer地址\n namesrvAddr: 127.0.0.1:9876\n\n', '765c17bc1d06fef027a6637d5c9582fc', '2023-04-18 10:14:48', '2023-04-18 10:14:48', NULL, '0:0:0:0:0:0:0:1', '', '', '试例模块', NULL, NULL, 'yaml', NULL, NULL); + +-- ---------------------------- +-- Table structure for config_info_aggr +-- ---------------------------- +DROP TABLE IF EXISTS `config_info_aggr`; +CREATE TABLE `config_info_aggr` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'data_id', + `group_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'group_id', + `datum_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'datum_id', + `content` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT '内容', + `gmt_modified` datetime NOT NULL COMMENT '修改时间', + `app_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL, + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT '租户字段', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_configinfoaggr_datagrouptenantdatum`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC, `datum_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = '增加租户字段' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of config_info_aggr +-- ---------------------------- + +-- ---------------------------- +-- Table structure for config_info_beta +-- ---------------------------- +DROP TABLE IF EXISTS `config_info_beta`; +CREATE TABLE `config_info_beta` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'data_id', + `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'group_id', + `app_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'app_name', + `content` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'content', + `beta_ips` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'betaIps', + `md5` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL COMMENT 'source user', + `src_ip` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'source ip', + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT '租户字段', + `encrypted_data_key` text CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL COMMENT '秘钥', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_configinfobeta_datagrouptenant`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = 'config_info_beta' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of config_info_beta +-- ---------------------------- + +-- ---------------------------- +-- Table structure for config_info_tag +-- ---------------------------- +DROP TABLE IF EXISTS `config_info_tag`; +CREATE TABLE `config_info_tag` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'data_id', + `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'group_id', + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT 'tenant_id', + `tag_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'tag_id', + `app_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'app_name', + `content` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'content', + `md5` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL COMMENT 'source user', + `src_ip` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'source ip', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_configinfotag_datagrouptenanttag`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC, `tag_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = 'config_info_tag' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of config_info_tag +-- ---------------------------- + +-- ---------------------------- +-- Table structure for config_tags_relation +-- ---------------------------- +DROP TABLE IF EXISTS `config_tags_relation`; +CREATE TABLE `config_tags_relation` ( + `id` bigint NOT NULL COMMENT 'id', + `tag_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'tag_name', + `tag_type` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'tag_type', + `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'data_id', + `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'group_id', + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT 'tenant_id', + `nid` bigint NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`nid`) USING BTREE, + UNIQUE INDEX `uk_configtagrelation_configidtag`(`id` ASC, `tag_name` ASC, `tag_type` ASC) USING BTREE, + INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = 'config_tag_relation' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of config_tags_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for group_capacity +-- ---------------------------- +DROP TABLE IF EXISTS `group_capacity`; +CREATE TABLE `group_capacity` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群', + `quota` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '配额,0表示使用默认值', + `usage` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用量', + `max_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', + `max_aggr_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数,,0表示使用默认值', + `max_aggr_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', + `max_history_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_group_id`(`group_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = '集群、各Group容量信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of group_capacity +-- ---------------------------- + +-- ---------------------------- +-- Table structure for his_config_info +-- ---------------------------- +DROP TABLE IF EXISTS `his_config_info`; +CREATE TABLE `his_config_info` ( + `id` bigint UNSIGNED NOT NULL, + `nid` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `data_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL, + `group_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL, + `app_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'app_name', + `content` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL, + `md5` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL, + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `src_user` text CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL, + `src_ip` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL, + `op_type` char(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL, + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT '租户字段', + `encrypted_data_key` text CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL COMMENT '秘钥', + PRIMARY KEY (`nid`) USING BTREE, + INDEX `idx_gmt_create`(`gmt_create` ASC) USING BTREE, + INDEX `idx_gmt_modified`(`gmt_modified` ASC) USING BTREE, + INDEX `idx_did`(`data_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = '多租户改造' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of his_config_info +-- ---------------------------- +INSERT INTO `his_config_info` VALUES (0, 24, 'yanzhu-rocketmq-dev.yml.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-log?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://101.201.68.182:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', 'd573ed2a6a9d3de7940dc767a390a07d', '2023-04-18 17:54:00', '2023-04-18 09:54:00', NULL, '0:0:0:0:0:0:0:1', 'I', '', NULL); +INSERT INTO `his_config_info` VALUES (33, 25, 'yanzhu-rocketmq-dev.yml.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-log?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://101.201.68.182:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', 'd573ed2a6a9d3de7940dc767a390a07d', '2023-04-18 17:56:18', '2023-04-18 09:56:19', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (5, 26, 'yanzhu-system-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-log?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://101.201.68.182:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n # datasource:\n # druid:\n # stat-view-servlet:\n # enabled: true\n # loginUsername: admin\n # loginPassword: 123456\n # dynamic:\n # druid:\n # initial-size: 5\n # min-idle: 5\n # maxActive: 20\n # maxWait: 60000\n # timeBetweenEvictionRunsMillis: 60000\n # minEvictableIdleTimeMillis: 300000\n # validationQuery: SELECT 1 FROM DUAL\n # testWhileIdle: true\n # testOnBorrow: false\n # testOnReturn: false\n # poolPreparedStatements: true\n # maxPoolPreparedStatementPerConnectionSize: 20\n # filters: stat,slf4j\n # connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n # datasource:\n # # 主库数据源\n # master:\n # driver-class-name: com.mysql.cj.jdbc.Driver\n # url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n # username: root\n # password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n\n\n\n \n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.system\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yanzhu\n licenseUrl: https://ruoyi.vip', 'cc6af346731ddc47a710bb3cfdc50794', '2023-04-18 18:07:42', '2023-04-18 10:07:43', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (5, 27, 'yanzhu-system-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-log?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://localhost:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n # datasource:\n # druid:\n # stat-view-servlet:\n # enabled: true\n # loginUsername: admin\n # loginPassword: 123456\n # dynamic:\n # druid:\n # initial-size: 5\n # min-idle: 5\n # maxActive: 20\n # maxWait: 60000\n # timeBetweenEvictionRunsMillis: 60000\n # minEvictableIdleTimeMillis: 300000\n # validationQuery: SELECT 1 FROM DUAL\n # testWhileIdle: true\n # testOnBorrow: false\n # testOnReturn: false\n # poolPreparedStatements: true\n # maxPoolPreparedStatementPerConnectionSize: 20\n # filters: stat,slf4j\n # connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n # datasource:\n # # 主库数据源\n # master:\n # driver-class-name: com.mysql.cj.jdbc.Driver\n # url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n # username: root\n # password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n\n\n\n \n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.system\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yanzhu\n licenseUrl: https://ruoyi.vip', '80f7510d7e26b73ce156c3ef07e1961c', '2023-04-18 18:11:12', '2023-04-18 10:11:13', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (5, 28, 'yanzhu-system-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://localhost:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n # datasource:\n # druid:\n # stat-view-servlet:\n # enabled: true\n # loginUsername: admin\n # loginPassword: 123456\n # dynamic:\n # druid:\n # initial-size: 5\n # min-idle: 5\n # maxActive: 20\n # maxWait: 60000\n # timeBetweenEvictionRunsMillis: 60000\n # minEvictableIdleTimeMillis: 300000\n # validationQuery: SELECT 1 FROM DUAL\n # testWhileIdle: true\n # testOnBorrow: false\n # testOnReturn: false\n # poolPreparedStatements: true\n # maxPoolPreparedStatementPerConnectionSize: 20\n # filters: stat,slf4j\n # connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n # datasource:\n # # 主库数据源\n # master:\n # driver-class-name: com.mysql.cj.jdbc.Driver\n # url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n # username: root\n # password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n\n\n\n \n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.system\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yanzhu\n licenseUrl: https://ruoyi.vip', '1f9d88e596db35d6157e2ecd8a20fd9c', '2023-04-18 18:12:19', '2023-04-18 10:12:20', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (0, 29, 'yanzhu-rocketmq-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring: \n redis:\n host: localhost\n port: 6379\n # password: \n datasource: \n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://127.0.0.1:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n\nsuning:\n rocketmq:\n # 生产者的组名\n producer:\n #是否开启自动配置\n isEnable: true\n # 发送同一类消息的设置为同一个group,保证唯一\n groupName: elink-service-message-producer\n # 消息最大长度 默认1024*4(4M)\n maxMessageSize: 4096\n # 发送消息超时时间,默认3000\n sendMsgTimeout: 3000\n # 发送消息失败重试次数,默认2\n retryTimesWhenSendFailed: 3\n group: produce-group\n # NameServer地址\n # name-server: 110.42.150.117:9876\n # 消费者的组名\n conumer:\n #是否开启自动配置\n isEnable: true\n # 官方建议:确保同一组中的每个消费者订阅相同的主题。\n groupName: elink-service-message-consumer\n # groupName: elink-service-message-producer\n group: conumer-group\n consumeThreadMin: 20\n consumeThreadMax: 64\n # 设置一次消费消息的条数,默认为1条\n consumeMessageBatchMaxSize: 1\n # NameServer地址\n namesrvAddr: 127.0.0.1:9876\n\n', '765c17bc1d06fef027a6637d5c9582fc', '2023-04-18 18:14:47', '2023-04-18 10:14:48', NULL, '0:0:0:0:0:0:0:1', 'I', '', NULL); +INSERT INTO `his_config_info` VALUES (33, 30, 'yanzhu-rocketmq-dev.yml.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring: \n redis:\n host: localhost\n port: 6379\n # password: \n datasource: \n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://127.0.0.1:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n\nsuning:\n rocketmq:\n # 生产者的组名\n producer:\n #是否开启自动配置\n isEnable: true\n # 发送同一类消息的设置为同一个group,保证唯一\n groupName: elink-service-message-producer\n # 消息最大长度 默认1024*4(4M)\n maxMessageSize: 4096\n # 发送消息超时时间,默认3000\n sendMsgTimeout: 3000\n # 发送消息失败重试次数,默认2\n retryTimesWhenSendFailed: 3\n group: produce-group\n # NameServer地址\n # name-server: 110.42.150.117:9876\n # 消费者的组名\n conumer:\n #是否开启自动配置\n isEnable: true\n # 官方建议:确保同一组中的每个消费者订阅相同的主题。\n groupName: elink-service-message-consumer\n # groupName: elink-service-message-producer\n group: conumer-group\n consumeThreadMin: 20\n consumeThreadMax: 64\n # 设置一次消费消息的条数,默认为1条\n consumeMessageBatchMaxSize: 1\n # NameServer地址\n namesrvAddr: 127.0.0.1:9876\n\n', '765c17bc1d06fef027a6637d5c9582fc', '2023-04-18 18:14:53', '2023-04-18 10:14:54', NULL, '0:0:0:0:0:0:0:1', 'D', '', NULL); +INSERT INTO `his_config_info` VALUES (5, 31, 'yanzhu-system-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n # datasource:\n # druid:\n # stat-view-servlet:\n # enabled: true\n # loginUsername: admin\n # loginPassword: 123456\n # dynamic:\n # druid:\n # initial-size: 5\n # min-idle: 5\n # maxActive: 20\n # maxWait: 60000\n # timeBetweenEvictionRunsMillis: 60000\n # minEvictableIdleTimeMillis: 300000\n # validationQuery: SELECT 1 FROM DUAL\n # testWhileIdle: true\n # testOnBorrow: false\n # testOnReturn: false\n # poolPreparedStatements: true\n # maxPoolPreparedStatementPerConnectionSize: 20\n # filters: stat,slf4j\n # connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n # datasource:\n # # 主库数据源\n # master:\n # driver-class-name: com.mysql.cj.jdbc.Driver\n # url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n # username: root\n # password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n\n\n\n \n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.system\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yanzhu\n licenseUrl: https://ruoyi.vip', 'daa2a9a93718c33dbb6c30fbc8591d22', '2023-04-18 18:18:04', '2023-04-18 10:18:04', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (30, 32, 'yanzhu-manage-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-log?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://101.201.68.182:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', 'd573ed2a6a9d3de7940dc767a390a07d', '2023-04-18 18:23:48', '2023-04-18 10:23:48', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (30, 33, 'yanzhu-manage-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: wc525123\n url: jdbc:mysql://localhost:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', '894747451da11d5464e4e1a8ae3f53ef', '2023-04-18 18:28:05', '2023-04-18 10:28:05', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (30, 34, 'yanzhu-manage-dev.yml', 'DEFAULT_GROUP', '', '# spring配置\nspring:\n redis:\n host: localhost\n port: 6379\n # password:\n # 分库分表配置\n shardingsphere:\n datasource:\n ds0:\n driver-class-name: com.mysql.cj.jdbc.Driver\n type: com.zaxxer.hikari.HikariDataSource\n username: root\n password: 123456\n jdbc-url: jdbc:mysql://127.0.0.1:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n names: ds0\n props:\n sql-show: true\n rules:\n sharding:\n sharding-algorithms:\n table-inline:\n props:\n algorithm-expression: sys_oper_log_$->{request_method}\n type: INLINE\n tables:\n sys_oper_log:\n actual-data-nodes: ds0.sys_oper_log_GET,ds0.sys_oper_log_POST,ds0.sys_oper_log_PUT,ds0.sys_oper_log_DELETE\n table-strategy:\n standard:\n sharding-algorithm-name: table-inline\n sharding-column: request_method\n # 动态多数据源配置\n datasource:\n dynamic:\n datasource:\n master:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n order:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/ry-order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_order数据源\n orders:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_account数据源\n account:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n # seata_product数据源\n product:\n username: root\n password: 123456\n url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n driver-class-name: com.mysql.cj.jdbc.Driver\n #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\n seata: true \n\n# seata配置\nseata:\n enabled: true\n # Seata 应用编号,默认为 ${spring.application.name}\n application-id: ${spring.application.name}\n # Seata 事务组编号,用于 TC 集群名\n tx-service-group: ${spring.application.name}-group\n # 关闭自动代理\n enable-auto-data-source-proxy: false\n # 服务配置项\n service:\n # 虚拟组和分组的映射\n vgroup-mapping:\n yanzhu-system-group: default\n # 分组和 Seata 服务的映射\n grouplist:\n default: 127.0.0.1:8091\n config:\n type: file\n registry:\n type: file\n \n# mybatis配置\nmybatis:\n # 搜索指定包别名\n typeAliasesPackage: com.yanzhu.manage\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapperLocations: classpath:mapper/**/*.xml\n\n# swagger配置\nswagger:\n title: 系统模块接口文档\n license: Powered By yz', '666f8dc7bf1dd7a1ce0c59c5fc928f67', '2023-04-18 18:29:16', '2023-04-18 10:29:16', 'nacos', '0:0:0:0:0:0:0:1', 'U', '', NULL); +INSERT INTO `his_config_info` VALUES (13, 35, 'config-sharding-jdbc.yaml', 'DEFAULT_GROUP', '', '# 以下配置截止版本为3.1\n# 配置文件中,必须配置的项目为schemaName,dataSources,并且sharidngRule,masterSlaveRule,配置其中一个(注意,除非server.yaml中定义了Orchestration,否则必须至少有一个config-xxxx配置文件),除此之外的其他项目为可选项\n# schema名称,每个文件都是单独的schema,多个schema则是多个yaml文件,yaml文件命名要求是config-xxxx.yaml格式,虽然没有强制要求,但推荐名称中的xxxx与配置的schemaName保持一致,方便维护\nschemaName: test \n\ndataSources: # 配置数据源列表,必须是有效的jdbc配置,目前仅支持MySQL与PostgreSQL,另外通过一些未公开(代码中可查,但可能会在未来有变化)的变量,可以配置来兼容其他支持JDBC的数据库,但由于没有足够的测试支持,可能会有严重的兼容性问题,配置时候要求至少有一个\n master_ds_0: # 数据源名称,可以是合法的字符串,目前的校验规则中,没有强制性要求,只要是合法的yaml字符串即可,但如果要用于分库分表配置,则需要有有意义的标志(在分库分表配置中详述),以下为目前公开的合法配置项目,不包含内部配置参数\n # 以下参数为必备参数\n # 这里的要求合法的jdbc连接串即可,目前尚未兼容MySQL 8.x,需要在maven编译时候,升级MySQL JDBC版本到5.1.46或者47版本(不建议升级到JDBC的8.x系列版本,需要修改源代码,并且无法通过很多测试case)\n url: jdbc:mysql://127.0.0.1:3306/demo_ds_slave_1?serverTimezone=UTC&useSSL=false \n # MySQL用户名\n username: root\n # MySQL用户的明文密码 \n password: password \n # 以下参数为可选参数,给出示例为默认配置,主要用于连接池控制\n #连接超时控制\n connectionTimeoutMilliseconds: 30000 \n # 连接空闲时间设置\n idleTimeoutMilliseconds: 60000 \n # 连接的最大持有时间,0为无限制\n maxLifetimeMilliseconds: 0 \n # 连接池中最大维持的连接数量\n maxPoolSize: 50 \n # 连接池的最小连接数量\n minPoolSize: 1 \n # 连接维护的时间间隔 atomikos框架需求\n maintenanceIntervalMilliseconds: 30000 \n # 以下配置的假设是,3307是3306的从库,3309,3310是3308的从库\n slave_ds_0:\n url: jdbc:mysql://127.0.0.1:3307/demo_ds_slave_1?serverTimezone=UTC&useSSL=false\n username: root\n password: password\n master_ds_1:\n url: jdbc:mysql://127.0.0.1:3308/demo_ds_slave_1?serverTimezone=UTC&useSSL=false\n username: root\n password: password\n slave_ds_1:\n url: jdbc:mysql://127.0.0.1:3309/demo_ds_slave_1?serverTimezone=UTC&useSSL=false\n username: root\n password: password\n slave_ds_1_slave2:\n url: jdbc:mysql://127.0.0.1:3310/demo_ds_slave_1?serverTimezone=UTC&useSSL=false\n username: root\n password: password\nmasterSlaveRule: # 这里配置这个规则的话,相当于是全局读写分离配置\n # 名称,合法的字符串即可,但如果涉及到在读写分离的基础上设置分库分表,则名称需要有意义才可以,另外,虽然目前没有强制要求,但主从库配置需要配置在实际关联的主从库上,如果配置的数据源之间主从是断开的状态,那么可能会发生写入的数据对于只读会话无法读取到的问题\n name: ds_rw \n # 如果一个会话发生了写入并且没有提交(显式打开事务),sharidng sphere在后续的路由中,select都会在主库执行,直到会话提交\n masterDataSourceName: master_ds_0 # 主库的DataSource名称\n slaveDataSourceNames: # 从库的DataSource列表,至少需要有一个\n - slave_ds_0\n # MasterSlaveLoadBalanceAlgorithm接口的实现类,允许自定义实现 默认提供两个,配置路径为io.shardingsphere.api.algorithm.masterslave下的RandomMasterSlaveLoadBalanceAlgorithm(随机Random)与RoundRobinMasterSlaveLoadBalanceAlgorithm(轮询:次数%从库数量) \n loadBalanceAlgorithmClassName: io.shardingsphere.api.algorithm.masterslave\n loadBalanceAlgorithmType: #从库负载均衡算法类型,可选值:ROUND_ROBIN,RANDOM。若loadBalanceAlgorithmClassName存在则忽略该配置,默认为ROUND_ROBIN\n\nshardingRule: # sharding的配置\n # 配置主要分两类,一类是对整个sharding规则所有表生效的默认配置,一个是sharing具体某张表时候的配置\n # 首先说默认配置\n masterSlaveRules: # 在shardingRule中也可以配置shardingRule,对分片生效,具体内容与全局masterSlaveRule一致,但语法为:\n master_test_0:\n masterDataSourceName: master_ds_0\n slaveDataSourceNames:\n - slave_ds_0\n master_test_1:\n masterDataSourceName: master_ds_1\n slaveDataSourceNames:\n - slave_ds_1\n - slave_ds_1_slave2\n # 这里的数据源允许是dataSources的配置项目或者masterSlaveRules配置的名称,配置为masterSlaveRule的话相当于就是配置读写分离了\n defaultDataSourceName: master_test_0 \n broadcastTables: # 广播表 这里配置的表列表,对于发生的所有数据变更,都会不经sharidng处理,而是直接发送到所有数据节点,注意此处为列表,每个项目为一个表名称\n - broad_1\n - broad_2\n bindingTables: # 绑定表,也就是实际上哪些配置的sharidng表规则需要实际生效的列表,配置为yaml列表,并且允许单个条目中以逗号切割,所配置表必须已经配置为逻辑表\n - sharding_t1\n - sharding_t2,sharding_t3\n defaultDatabaseShardingStrategy: # 默认库级别sharidng规则,对应代码中ShardingStrategy接口的实现类,目前支持none,inline,hint,complex,standard五种配置 注意此处默认配置仅可以配置五个中的一个\n # 规则配置同样适合表sharding配置,同样是在这些算法中选择\n none: # 不配置任何规则,SQL会被发给所有节点去执行,这个规则没有子项目可以配置\n inline: # 行表达式分片\n # 分片列名称\n shardingColumn: test_id \n # 分片表达式,根据指定的表达式计算得到需要路由到的数据源名称 需要是合法的groovy表达式,示例配置中,取余为0则语句路由到master_test_0,取余为1则路由到master_test_1\n algorithmExpression: master_test_${test_id % 2} \n hint: #基于标记的sharding分片\n shardingAlgorithm: # 需要是HintShardingAlgorithm接口的实现,目前代码中,仅有为测试目的实现的OrderDatabaseHintShardingAlgorithm,没有生产环境可用的实现\n complex: # 支持多列的shariding,目前无生产可用实现\n shardingColumns: # 逗号切割的列\n shardingAlgorithm: # ComplexKeysShardingAlgorithm接口的实现类\n standard: # 单列sharidng算法,需要配合对应的preciseShardingAlgorithm,rangeShardingAlgorithm接口的实现使用,目前无生产可用实现\n shardingColumn: # 列名,允许单列\n preciseShardingAlgorithm: # preciseShardingAlgorithm接口的实现类\n rangeShardingAlgorithm: # rangeShardingAlgorithm接口的实现类\n defaultTableStrategy: #配置参考defaultDatabaseShardingStrategy,区别在于,inline算法的配置中,algorithmExpression的配置算法结果需要是实际的物理表名称,而非数据源名称\n defaultKeyGenerator: #默认的主键生成算法 如果没有设置,默认为SNOWFLAKE算法\n column: # 自增键对应的列名称\n type: #自增键的类型,主要用于调用内置的主键生成算法有三个可用值:SNOWFLAKE(时间戳+worker id+自增id),UUID(java.util.UUID类生成的随机UUID),LEAF,其中Snowflake算法与UUID算法已经实现,LEAF目前(2018-01-14)尚未实现\n className: # 非内置的其他实现了KeyGenerator接口的类,需要注意,如果设置这个,就不能设置type,否则type的设置会覆盖class的设置\n props:\n # 定制算法需要设置的参数,比如SNOWFLAKE算法的worker.id与max.tolerate.time.difference.milliseconds\n tables: #配置表sharding的主要位置\n sharding_t1:\n # sharidng 表对应的数据源以及物理名称,需要用表达式处理,表示表实际上在哪些数据源存在,配置示例中,意思是总共存在4个分片master_test_0.t_order0,master_test_0.t_order1,master_test_1.t_order0,master_test_1.t_order1\n actualDataNodes: master_test_${0..1}.t_order${0..1} \n # 需要注意的是,必须保证设置databaseStrategy可以路由到唯一的dataSource,tableStrategy可以路由到dataSource中唯一的物理表上,否则可能导致错误:一个insert语句被插入到多个实际物理表中\n databaseStrategy: # 局部设置会覆盖全局设置,参考defaultDatabaseShardingStrategy\n tableStrategy: # 局部设置会覆盖全局设置,参考defaultTableStrategy\n keyGenerator: # 局部设置会覆盖全局设置,参考defaultKeyGenerator\n logicIndex: # 逻辑索引名称 由于Oracle,PG这种数据库中,索引与表共用命名空间,如果接受到drop index语句,执行之前,会通过这个名称配置的确定对应的实际物理表名称\nprops:\n sql.show: #是否开启SQL显示,默认值: false\n acceptor.size: # accept连接的线程数量,默认为cpu核数2倍\n executor.size: #工作线程数量最大,默认值: 无限制\n max.connections.size.per.query: # 每个查询可以打开的最大连接数量,默认为1\n proxy.frontend.flush.threshold: # proxy的服务时候,对于单个大查询,每多少个网络包返回一次\n check.table.metadata.enabled: #是否在启动时检查分表元数据一致性,默认值: false\n proxy.transaction.type: # 默认LOCAL,proxy的事务模型 允许LOCAL,XA,BASE三个值 LOCAL无分布式事务,XA则是采用atomikos实现的分布式事务 BASE目前尚未实现\n proxy.opentracing.enabled: # 是否启用opentracing\n proxy.backend.use.nio: # 是否采用netty的NIO机制连接后端数据库,默认False ,使用epoll机制\n proxy.backend.max.connections: # 使用NIO而非epoll的话,proxy后台连接每个netty客户端允许的最大连接数量(注意不是数据库连接限制) 默认为8\n proxy.backend.connection.timeout.seconds: #使用nio而非epoll的话,proxy后台连接的超时时间,默认60s\n check.table.metadata.enabled: # 是否在启动时候,检查sharing的表的实际元数据是否一致,默认False\n\n#数据治理\norchestration:\n name: #数据治理实例名称\n overwrite: #本地配置是否覆盖注册中心配置。如果可覆盖,每次启动都以本地配置为准\n registry: #注册中心配置\n serverLists: #连接注册中心服务器的列表。包括IP地址和端口号。多个地址用逗号分隔。如: host1:2181,host2:2181\n namespace: #注册中心的命名空间\n digest: #连接注册中心的权限令牌。缺省为不需要权限验证\n operationTimeoutMilliseconds: #操作超时的毫秒数,默认500毫秒\n maxRetries: #连接失败后的最大重试次数,默认3次\n retryIntervalMilliseconds: #重试间隔毫秒数,默认500毫秒\n timeToLiveSeconds: #临时节点存活秒数,默认60秒', 'e24621fe292306e3777398da496247b1', '2023-04-18 18:52:04', '2023-04-18 10:52:04', NULL, '0:0:0:0:0:0:0:1', 'D', '', NULL); + +-- ---------------------------- +-- Table structure for permissions +-- ---------------------------- +DROP TABLE IF EXISTS `permissions`; +CREATE TABLE `permissions` ( + `role` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `resource` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `action` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + UNIQUE INDEX `uk_role_permission`(`role` ASC, `resource` ASC, `action` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of permissions +-- ---------------------------- + +-- ---------------------------- +-- Table structure for roles +-- ---------------------------- +DROP TABLE IF EXISTS `roles`; +CREATE TABLE `roles` ( + `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `role` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + UNIQUE INDEX `idx_user_role`(`username` ASC, `role` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of roles +-- ---------------------------- +INSERT INTO `roles` VALUES ('nacos', 'ROLE_ADMIN'); + +-- ---------------------------- +-- Table structure for tenant_capacity +-- ---------------------------- +DROP TABLE IF EXISTS `tenant_capacity`; +CREATE TABLE `tenant_capacity` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL DEFAULT '' COMMENT 'Tenant ID', + `quota` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '配额,0表示使用默认值', + `usage` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用量', + `max_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', + `max_aggr_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数', + `max_aggr_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', + `max_history_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_tenant_id`(`tenant_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = '租户容量信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tenant_capacity +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tenant_info +-- ---------------------------- +DROP TABLE IF EXISTS `tenant_info`; +CREATE TABLE `tenant_info` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `kp` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL COMMENT 'kp', + `tenant_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT 'tenant_id', + `tenant_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT '' COMMENT 'tenant_name', + `tenant_desc` varchar(256) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'tenant_desc', + `create_source` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT 'create_source', + `gmt_create` bigint NOT NULL COMMENT '创建时间', + `gmt_modified` bigint NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_tenant_info_kptenantid`(`kp` ASC, `tenant_id` ASC) USING BTREE, + INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin COMMENT = 'tenant_info' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tenant_info +-- ---------------------------- + +-- ---------------------------- +-- Table structure for users +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `password` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `enabled` tinyint(1) NOT NULL, + PRIMARY KEY (`username`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of users +-- ---------------------------- +INSERT INTO `users` VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', 1); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/docsql/quartz.sql b/docsql/quartz.sql new file mode 100644 index 00000000..cee613b7 --- /dev/null +++ b/docsql/quartz.sql @@ -0,0 +1,174 @@ +DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; +DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; +DROP TABLE IF EXISTS QRTZ_LOCKS; +DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; +DROP TABLE IF EXISTS QRTZ_CALENDARS; + +-- ---------------------------- +-- 1、存储每一个已配置的 jobDetail 的详细信息 +-- ---------------------------- +create table QRTZ_JOB_DETAILS ( + sched_name varchar(120) not null comment '调度名称', + job_name varchar(200) not null comment '任务名称', + job_group varchar(200) not null comment '任务组名', + description varchar(250) null comment '相关介绍', + job_class_name varchar(250) not null comment '执行任务类名称', + is_durable varchar(1) not null comment '是否持久化', + is_nonconcurrent varchar(1) not null comment '是否并发', + is_update_data varchar(1) not null comment '是否更新数据', + requests_recovery varchar(1) not null comment '是否接受恢复执行', + job_data blob null comment '存放持久化job对象', + primary key (sched_name, job_name, job_group) +) engine=innodb comment = '任务详细信息表'; + +-- ---------------------------- +-- 2、 存储已配置的 Trigger 的信息 +-- ---------------------------- +create table QRTZ_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment '触发器的名字', + trigger_group varchar(200) not null comment '触发器所属组的名字', + job_name varchar(200) not null comment 'qrtz_job_details表job_name的外键', + job_group varchar(200) not null comment 'qrtz_job_details表job_group的外键', + description varchar(250) null comment '相关介绍', + next_fire_time bigint(13) null comment '上一次触发时间(毫秒)', + prev_fire_time bigint(13) null comment '下一次触发时间(默认为-1表示不触发)', + priority integer null comment '优先级', + trigger_state varchar(16) not null comment '触发器状态', + trigger_type varchar(8) not null comment '触发器的类型', + start_time bigint(13) not null comment '开始时间', + end_time bigint(13) null comment '结束时间', + calendar_name varchar(200) null comment '日程表名称', + misfire_instr smallint(2) null comment '补偿执行的策略', + job_data blob null comment '存放持久化job对象', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, job_name, job_group) references QRTZ_JOB_DETAILS(sched_name, job_name, job_group) +) engine=innodb comment = '触发器详细信息表'; + +-- ---------------------------- +-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 +-- ---------------------------- +create table QRTZ_SIMPLE_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + repeat_count bigint(7) not null comment '重复的次数统计', + repeat_interval bigint(12) not null comment '重复的间隔时间', + times_triggered bigint(10) not null comment '已经触发的次数', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = '简单触发器的信息表'; + +-- ---------------------------- +-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 +-- ---------------------------- +create table QRTZ_CRON_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + cron_expression varchar(200) not null comment 'cron表达式', + time_zone_id varchar(80) comment '时区', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = 'Cron类型的触发器表'; + +-- ---------------------------- +-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) +-- ---------------------------- +create table QRTZ_BLOB_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + blob_data blob null comment '存放持久化Trigger对象', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = 'Blob类型的触发器表'; + +-- ---------------------------- +-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 +-- ---------------------------- +create table QRTZ_CALENDARS ( + sched_name varchar(120) not null comment '调度名称', + calendar_name varchar(200) not null comment '日历名称', + calendar blob not null comment '存放持久化calendar对象', + primary key (sched_name, calendar_name) +) engine=innodb comment = '日历信息表'; + +-- ---------------------------- +-- 7、 存储已暂停的 Trigger 组的信息 +-- ---------------------------- +create table QRTZ_PAUSED_TRIGGER_GRPS ( + sched_name varchar(120) not null comment '调度名称', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + primary key (sched_name, trigger_group) +) engine=innodb comment = '暂停的触发器表'; + +-- ---------------------------- +-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 +-- ---------------------------- +create table QRTZ_FIRED_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + entry_id varchar(95) not null comment '调度器实例id', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + instance_name varchar(200) not null comment '调度器实例名', + fired_time bigint(13) not null comment '触发的时间', + sched_time bigint(13) not null comment '定时器制定的时间', + priority integer not null comment '优先级', + state varchar(16) not null comment '状态', + job_name varchar(200) null comment '任务名称', + job_group varchar(200) null comment '任务组名', + is_nonconcurrent varchar(1) null comment '是否并发', + requests_recovery varchar(1) null comment '是否接受恢复执行', + primary key (sched_name, entry_id) +) engine=innodb comment = '已触发的触发器表'; + +-- ---------------------------- +-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 +-- ---------------------------- +create table QRTZ_SCHEDULER_STATE ( + sched_name varchar(120) not null comment '调度名称', + instance_name varchar(200) not null comment '实例名称', + last_checkin_time bigint(13) not null comment '上次检查时间', + checkin_interval bigint(13) not null comment '检查间隔时间', + primary key (sched_name, instance_name) +) engine=innodb comment = '调度器状态表'; + +-- ---------------------------- +-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) +-- ---------------------------- +create table QRTZ_LOCKS ( + sched_name varchar(120) not null comment '调度名称', + lock_name varchar(40) not null comment '悲观锁名称', + primary key (sched_name, lock_name) +) engine=innodb comment = '存储的悲观锁信息表'; + +-- ---------------------------- +-- 11、 Quartz集群实现同步机制的行锁表 +-- ---------------------------- +create table QRTZ_SIMPROP_TRIGGERS ( + sched_name varchar(120) not null comment '调度名称', + trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', + trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', + str_prop_1 varchar(512) null comment 'String类型的trigger的第一个参数', + str_prop_2 varchar(512) null comment 'String类型的trigger的第二个参数', + str_prop_3 varchar(512) null comment 'String类型的trigger的第三个参数', + int_prop_1 int null comment 'int类型的trigger的第一个参数', + int_prop_2 int null comment 'int类型的trigger的第二个参数', + long_prop_1 bigint null comment 'long类型的trigger的第一个参数', + long_prop_2 bigint null comment 'long类型的trigger的第二个参数', + dec_prop_1 numeric(13,4) null comment 'decimal类型的trigger的第一个参数', + dec_prop_2 numeric(13,4) null comment 'decimal类型的trigger的第二个参数', + bool_prop_1 varchar(1) null comment 'Boolean类型的trigger的第一个参数', + bool_prop_2 varchar(1) null comment 'Boolean类型的trigger的第二个参数', + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +) engine=innodb comment = '同步机制的行锁表'; + +commit; \ No newline at end of file diff --git a/docsql/ry-order.sql b/docsql/ry-order.sql new file mode 100644 index 00000000..d1375783 --- /dev/null +++ b/docsql/ry-order.sql @@ -0,0 +1,37 @@ +/* + Navicat Premium Data Transfer + + Source Server : 101.201.68.182 + Source Server Type : MySQL + Source Server Version : 80030 + Source Host : 101.201.68.182:3306 + Source Schema : ry-order + + Target Server Type : MySQL + Target Server Version : 80030 + File Encoding : 65001 + + Date: 11/03/2023 15:27:48 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for sys_order +-- ---------------------------- +DROP TABLE IF EXISTS `sys_order`; +CREATE TABLE `sys_order` ( + `order_id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `user_id` bigint NOT NULL COMMENT '用户编号', + `STATUS` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '状态(0交易成功 1交易失败)', + `order_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单流水', + PRIMARY KEY (`order_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_order +-- ---------------------------- +INSERT INTO `sys_order` VALUES (1, 1, '0', '826980f3e3d04092aa337268b830089e'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/docsql/ry_cloud.sql b/docsql/ry_cloud.sql new file mode 100644 index 00000000..9200dbec --- /dev/null +++ b/docsql/ry_cloud.sql @@ -0,0 +1,695 @@ +SET NAMES utf8mb4; + +-- ---------------------------- +-- 1、部门表 +-- ---------------------------- +drop table if exists sys_dept; +create table sys_dept ( + dept_id bigint(20) not null auto_increment comment '部门id', + parent_id bigint(20) default 0 comment '父部门id', + ancestors varchar(50) default '' comment '祖级列表', + dept_name varchar(30) default '' comment '部门名称', + order_num int(4) default 0 comment '显示顺序', + leader varchar(20) default null comment '负责人', + phone varchar(11) default null comment '联系电话', + email varchar(50) default null comment '邮箱', + status char(1) default '0' comment '部门状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + primary key (dept_id) +) engine=innodb auto_increment=200 comment = '部门表'; + +-- ---------------------------- +-- 初始化-部门表数据 +-- ---------------------------- +insert into sys_dept values(100, 0, '0', '若依科技', 0, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); +insert into sys_dept values(109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); + + +-- ---------------------------- +-- 2、用户信息表 +-- ---------------------------- +drop table if exists sys_user; +create table sys_user ( + user_id bigint(20) not null auto_increment comment '用户ID', + dept_id bigint(20) default null comment '部门ID', + user_name varchar(30) not null comment '用户账号', + nick_name varchar(30) not null comment '用户昵称', + user_type varchar(2) default '00' comment '用户类型(00系统用户)', + email varchar(50) default '' comment '用户邮箱', + phonenumber varchar(11) default '' comment '手机号码', + sex char(1) default '0' comment '用户性别(0男 1女 2未知)', + avatar varchar(100) default '' comment '头像地址', + password varchar(100) default '' comment '密码', + status char(1) default '0' comment '帐号状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + login_ip varchar(128) default '' comment '最后登录IP', + login_date datetime comment '最后登录时间', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (user_id) +) engine=innodb auto_increment=100 comment = '用户信息表'; + +-- ---------------------------- +-- 初始化-用户信息表数据 +-- ---------------------------- +insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员'); +insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员'); + + +-- ---------------------------- +-- 3、岗位信息表 +-- ---------------------------- +drop table if exists sys_post; +create table sys_post +( + post_id bigint(20) not null auto_increment comment '岗位ID', + post_code varchar(64) not null comment '岗位编码', + post_name varchar(50) not null comment '岗位名称', + post_sort int(4) not null comment '显示顺序', + status char(1) not null comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (post_id) +) engine=innodb comment = '岗位信息表'; + +-- ---------------------------- +-- 初始化-岗位信息表数据 +-- ---------------------------- +insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', sysdate(), '', null, ''); +insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 4、角色信息表 +-- ---------------------------- +drop table if exists sys_role; +create table sys_role ( + role_id bigint(20) not null auto_increment comment '角色ID', + role_name varchar(30) not null comment '角色名称', + role_key varchar(100) not null comment '角色权限字符串', + role_sort int(4) not null comment '显示顺序', + data_scope char(1) default '1' comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', + dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示', + status char(1) not null comment '角色状态(0正常 1停用)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (role_id) +) engine=innodb auto_increment=100 comment = '角色信息表'; + +-- ---------------------------- +-- 初始化-角色信息表数据 +-- ---------------------------- +insert into sys_role values('1', '超级管理员', 'admin', 1, 1, 1, 1, '0', '0', 'admin', sysdate(), '', null, '超级管理员'); +insert into sys_role values('2', '普通角色', 'common', 2, 2, 1, 1, '0', '0', 'admin', sysdate(), '', null, '普通角色'); + + +-- ---------------------------- +-- 5、菜单权限表 +-- ---------------------------- +drop table if exists sys_menu; +create table sys_menu ( + menu_id bigint(20) not null auto_increment comment '菜单ID', + menu_name varchar(50) not null comment '菜单名称', + parent_id bigint(20) default 0 comment '父菜单ID', + order_num int(4) default 0 comment '显示顺序', + path varchar(200) default '' comment '路由地址', + component varchar(255) default null comment '组件路径', + query varchar(255) default null comment '路由参数', + is_frame int(1) default 1 comment '是否为外链(0是 1否)', + is_cache int(1) default 0 comment '是否缓存(0缓存 1不缓存)', + menu_type char(1) default '' comment '菜单类型(M目录 C菜单 F按钮)', + visible char(1) default 0 comment '菜单状态(0显示 1隐藏)', + status char(1) default 0 comment '菜单状态(0正常 1停用)', + perms varchar(100) default null comment '权限标识', + icon varchar(100) default '#' comment '菜单图标', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default '' comment '备注', + primary key (menu_id) +) engine=innodb auto_increment=2000 comment = '菜单权限表'; + +-- ---------------------------- +-- 初始化-菜单信息表数据 +-- ---------------------------- +-- 一级菜单 +insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '系统管理目录'); +insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录'); +insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录'); +insert into sys_menu values('4', '研筑官网', '0', '4', 'http://www.sxyanzhu.com', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '研筑官网地址'); +-- 二级菜单 +insert into sys_menu values('100', '用户管理', '1', '1', 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', sysdate(), '', null, '用户管理菜单'); +insert into sys_menu values('101', '角色管理', '1', '2', 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', sysdate(), '', null, '角色管理菜单'); +insert into sys_menu values('102', '菜单管理', '1', '3', 'menu', 'system/menu/index', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'tree-table', 'admin', sysdate(), '', null, '菜单管理菜单'); +insert into sys_menu values('103', '部门管理', '1', '4', 'dept', 'system/dept/index', '', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', sysdate(), '', null, '部门管理菜单'); +insert into sys_menu values('104', '岗位管理', '1', '5', 'post', 'system/post/index', '', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', sysdate(), '', null, '岗位管理菜单'); +insert into sys_menu values('105', '字典管理', '1', '6', 'dict', 'system/dict/index', '', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', sysdate(), '', null, '字典管理菜单'); +insert into sys_menu values('106', '参数设置', '1', '7', 'config', 'system/config/index', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', sysdate(), '', null, '参数设置菜单'); +insert into sys_menu values('107', '通知公告', '1', '8', 'notice', 'system/notice/index', '', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', sysdate(), '', null, '通知公告菜单'); +insert into sys_menu values('108', '日志管理', '1', '9', 'log', '', '', 1, 0, 'M', '0', '0', '', 'log', 'admin', sysdate(), '', null, '日志管理菜单'); +insert into sys_menu values('109', '在线用户', '2', '1', 'online', 'monitor/online/index', '', 1, 0, 'C', '0', '0', 'monitor:online:list', 'online', 'admin', sysdate(), '', null, '在线用户菜单'); +insert into sys_menu values('110', '定时任务', '2', '2', 'job', 'monitor/job/index', '', 1, 0, 'C', '0', '0', 'monitor:job:list', 'job', 'admin', sysdate(), '', null, '定时任务菜单'); +insert into sys_menu values('111', 'Sentinel控制台', '2', '3', 'http://localhost:8718', '', '', 0, 0, 'C', '0', '0', 'monitor:sentinel:list', 'sentinel', 'admin', sysdate(), '', null, '流量控制菜单'); +insert into sys_menu values('112', 'Nacos控制台', '2', '4', 'http://localhost:8848/nacos', '', '', 0, 0, 'C', '0', '0', 'monitor:nacos:list', 'nacos', 'admin', sysdate(), '', null, '服务治理菜单'); +insert into sys_menu values('113', 'Admin控制台', '2', '5', 'http://localhost:9100/login', '', '', 0, 0, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', sysdate(), '', null, '服务监控菜单'); +insert into sys_menu values('114', '表单构建', '3', '1', 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 'admin', sysdate(), '', null, '表单构建菜单'); +insert into sys_menu values('115', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 'admin', sysdate(), '', null, '代码生成菜单'); +insert into sys_menu values('116', '系统接口', '3', '3', 'http://localhost:8080/swagger-ui/index.html', '', '', 0, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', sysdate(), '', null, '系统接口菜单'); +-- 三级菜单 +insert into sys_menu values('500', '操作日志', '108', '1', 'operlog', 'system/operlog/index', '', 1, 0, 'C', '0', '0', 'system:operlog:list', 'form', 'admin', sysdate(), '', null, '操作日志菜单'); +insert into sys_menu values('501', '登录日志', '108', '2', 'logininfor', 'system/logininfor/index', '', 1, 0, 'C', '0', '0', 'system:logininfor:list', 'logininfor', 'admin', sysdate(), '', null, '登录日志菜单'); +-- 用户管理按钮 +insert into sys_menu values('1000', '用户查询', '100', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1001', '用户新增', '100', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1002', '用户修改', '100', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1003', '用户删除', '100', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1004', '用户导出', '100', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1005', '用户导入', '100', '6', '', '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1006', '重置密码', '100', '7', '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', sysdate(), '', null, ''); +-- 角色管理按钮 +insert into sys_menu values('1007', '角色查询', '101', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1008', '角色新增', '101', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1009', '角色修改', '101', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1010', '角色删除', '101', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1011', '角色导出', '101', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:role:export', '#', 'admin', sysdate(), '', null, ''); +-- 菜单管理按钮 +insert into sys_menu values('1012', '菜单查询', '102', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1013', '菜单新增', '102', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1014', '菜单修改', '102', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1015', '菜单删除', '102', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', sysdate(), '', null, ''); +-- 部门管理按钮 +insert into sys_menu values('1016', '部门查询', '103', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1017', '部门新增', '103', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1018', '部门修改', '103', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1019', '部门删除', '103', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', sysdate(), '', null, ''); +-- 岗位管理按钮 +insert into sys_menu values('1020', '岗位查询', '104', '1', '', '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1021', '岗位新增', '104', '2', '', '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1022', '岗位修改', '104', '3', '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1023', '岗位删除', '104', '4', '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1024', '岗位导出', '104', '5', '', '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', sysdate(), '', null, ''); +-- 字典管理按钮 +insert into sys_menu values('1025', '字典查询', '105', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1026', '字典新增', '105', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1027', '字典修改', '105', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1028', '字典删除', '105', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1029', '字典导出', '105', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', sysdate(), '', null, ''); +-- 参数设置按钮 +insert into sys_menu values('1030', '参数查询', '106', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1031', '参数新增', '106', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1032', '参数修改', '106', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1033', '参数删除', '106', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1034', '参数导出', '106', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', sysdate(), '', null, ''); +-- 通知公告按钮 +insert into sys_menu values('1035', '公告查询', '107', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1036', '公告新增', '107', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1037', '公告修改', '107', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1038', '公告删除', '107', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:remove', '#', 'admin', sysdate(), '', null, ''); +-- 操作日志按钮 +insert into sys_menu values('1039', '操作查询', '500', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:operlog:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1040', '操作删除', '500', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:operlog:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1041', '日志导出', '500', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:operlog:export', '#', 'admin', sysdate(), '', null, ''); +-- 登录日志按钮 +insert into sys_menu values('1042', '登录查询', '501', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:logininfor:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1043', '登录删除', '501', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:logininfor:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1044', '日志导出', '501', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:logininfor:export', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1045', '账户解锁', '501', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:logininfor:unlock', '#', 'admin', sysdate(), '', null, ''); +-- 在线用户按钮 +insert into sys_menu values('1046', '在线查询', '109', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1047', '批量强退', '109', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:batchLogout', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1048', '单条强退', '109', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:forceLogout', '#', 'admin', sysdate(), '', null, ''); +-- 定时任务按钮 +insert into sys_menu values('1049', '任务查询', '110', '1', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1050', '任务新增', '110', '2', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:add', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1051', '任务修改', '110', '3', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1052', '任务删除', '110', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1053', '状态修改', '110', '5', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:changeStatus', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1054', '任务导出', '110', '6', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:export', '#', 'admin', sysdate(), '', null, ''); +-- 代码生成按钮 +insert into sys_menu values('1055', '生成查询', '115', '1', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:query', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1056', '生成修改', '115', '2', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:edit', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1057', '生成删除', '115', '3', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:remove', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1058', '导入代码', '115', '2', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1059', '预览代码', '115', '4', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview', '#', 'admin', sysdate(), '', null, ''); +insert into sys_menu values('1060', '生成代码', '115', '5', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code', '#', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 6、用户和角色关联表 用户N-1角色 +-- ---------------------------- +drop table if exists sys_user_role; +create table sys_user_role ( + user_id bigint(20) not null comment '用户ID', + role_id bigint(20) not null comment '角色ID', + primary key(user_id, role_id) +) engine=innodb comment = '用户和角色关联表'; + +-- ---------------------------- +-- 初始化-用户和角色关联表数据 +-- ---------------------------- +insert into sys_user_role values ('1', '1'); +insert into sys_user_role values ('2', '2'); + + +-- ---------------------------- +-- 7、角色和菜单关联表 角色1-N菜单 +-- ---------------------------- +drop table if exists sys_role_menu; +create table sys_role_menu ( + role_id bigint(20) not null comment '角色ID', + menu_id bigint(20) not null comment '菜单ID', + primary key(role_id, menu_id) +) engine=innodb comment = '角色和菜单关联表'; + +-- ---------------------------- +-- 初始化-角色和菜单关联表数据 +-- ---------------------------- +insert into sys_role_menu values ('2', '1'); +insert into sys_role_menu values ('2', '2'); +insert into sys_role_menu values ('2', '3'); +insert into sys_role_menu values ('2', '4'); +insert into sys_role_menu values ('2', '100'); +insert into sys_role_menu values ('2', '101'); +insert into sys_role_menu values ('2', '102'); +insert into sys_role_menu values ('2', '103'); +insert into sys_role_menu values ('2', '104'); +insert into sys_role_menu values ('2', '105'); +insert into sys_role_menu values ('2', '106'); +insert into sys_role_menu values ('2', '107'); +insert into sys_role_menu values ('2', '108'); +insert into sys_role_menu values ('2', '109'); +insert into sys_role_menu values ('2', '110'); +insert into sys_role_menu values ('2', '111'); +insert into sys_role_menu values ('2', '112'); +insert into sys_role_menu values ('2', '113'); +insert into sys_role_menu values ('2', '114'); +insert into sys_role_menu values ('2', '115'); +insert into sys_role_menu values ('2', '116'); +insert into sys_role_menu values ('2', '500'); +insert into sys_role_menu values ('2', '501'); +insert into sys_role_menu values ('2', '1000'); +insert into sys_role_menu values ('2', '1001'); +insert into sys_role_menu values ('2', '1002'); +insert into sys_role_menu values ('2', '1003'); +insert into sys_role_menu values ('2', '1004'); +insert into sys_role_menu values ('2', '1005'); +insert into sys_role_menu values ('2', '1006'); +insert into sys_role_menu values ('2', '1007'); +insert into sys_role_menu values ('2', '1008'); +insert into sys_role_menu values ('2', '1009'); +insert into sys_role_menu values ('2', '1010'); +insert into sys_role_menu values ('2', '1011'); +insert into sys_role_menu values ('2', '1012'); +insert into sys_role_menu values ('2', '1013'); +insert into sys_role_menu values ('2', '1014'); +insert into sys_role_menu values ('2', '1015'); +insert into sys_role_menu values ('2', '1016'); +insert into sys_role_menu values ('2', '1017'); +insert into sys_role_menu values ('2', '1018'); +insert into sys_role_menu values ('2', '1019'); +insert into sys_role_menu values ('2', '1020'); +insert into sys_role_menu values ('2', '1021'); +insert into sys_role_menu values ('2', '1022'); +insert into sys_role_menu values ('2', '1023'); +insert into sys_role_menu values ('2', '1024'); +insert into sys_role_menu values ('2', '1025'); +insert into sys_role_menu values ('2', '1026'); +insert into sys_role_menu values ('2', '1027'); +insert into sys_role_menu values ('2', '1028'); +insert into sys_role_menu values ('2', '1029'); +insert into sys_role_menu values ('2', '1030'); +insert into sys_role_menu values ('2', '1031'); +insert into sys_role_menu values ('2', '1032'); +insert into sys_role_menu values ('2', '1033'); +insert into sys_role_menu values ('2', '1034'); +insert into sys_role_menu values ('2', '1035'); +insert into sys_role_menu values ('2', '1036'); +insert into sys_role_menu values ('2', '1037'); +insert into sys_role_menu values ('2', '1038'); +insert into sys_role_menu values ('2', '1039'); +insert into sys_role_menu values ('2', '1040'); +insert into sys_role_menu values ('2', '1041'); +insert into sys_role_menu values ('2', '1042'); +insert into sys_role_menu values ('2', '1043'); +insert into sys_role_menu values ('2', '1044'); +insert into sys_role_menu values ('2', '1045'); +insert into sys_role_menu values ('2', '1046'); +insert into sys_role_menu values ('2', '1047'); +insert into sys_role_menu values ('2', '1048'); +insert into sys_role_menu values ('2', '1049'); +insert into sys_role_menu values ('2', '1050'); +insert into sys_role_menu values ('2', '1051'); +insert into sys_role_menu values ('2', '1052'); +insert into sys_role_menu values ('2', '1053'); +insert into sys_role_menu values ('2', '1054'); +insert into sys_role_menu values ('2', '1055'); +insert into sys_role_menu values ('2', '1056'); +insert into sys_role_menu values ('2', '1057'); +insert into sys_role_menu values ('2', '1058'); +insert into sys_role_menu values ('2', '1059'); +insert into sys_role_menu values ('2', '1060'); + +-- ---------------------------- +-- 8、角色和部门关联表 角色1-N部门 +-- ---------------------------- +drop table if exists sys_role_dept; +create table sys_role_dept ( + role_id bigint(20) not null comment '角色ID', + dept_id bigint(20) not null comment '部门ID', + primary key(role_id, dept_id) +) engine=innodb comment = '角色和部门关联表'; + +-- ---------------------------- +-- 初始化-角色和部门关联表数据 +-- ---------------------------- +insert into sys_role_dept values ('2', '100'); +insert into sys_role_dept values ('2', '101'); +insert into sys_role_dept values ('2', '105'); + + +-- ---------------------------- +-- 9、用户与岗位关联表 用户1-N岗位 +-- ---------------------------- +drop table if exists sys_user_post; +create table sys_user_post +( + user_id bigint(20) not null comment '用户ID', + post_id bigint(20) not null comment '岗位ID', + primary key (user_id, post_id) +) engine=innodb comment = '用户与岗位关联表'; + +-- ---------------------------- +-- 初始化-用户与岗位关联表数据 +-- ---------------------------- +insert into sys_user_post values ('1', '1'); +insert into sys_user_post values ('2', '2'); + + +-- ---------------------------- +-- 10、操作日志记录 +-- ---------------------------- +drop table if exists sys_oper_log; +create table sys_oper_log ( + oper_id bigint(20) not null auto_increment comment '日志主键', + title varchar(50) default '' comment '模块标题', + business_type int(2) default 0 comment '业务类型(0其它 1新增 2修改 3删除)', + method varchar(100) default '' comment '方法名称', + request_method varchar(10) default '' comment '请求方式', + operator_type int(1) default 0 comment '操作类别(0其它 1后台用户 2手机端用户)', + oper_name varchar(50) default '' comment '操作人员', + dept_name varchar(50) default '' comment '部门名称', + oper_url varchar(255) default '' comment '请求URL', + oper_ip varchar(128) default '' comment '主机地址', + oper_location varchar(255) default '' comment '操作地点', + oper_param varchar(2000) default '' comment '请求参数', + json_result varchar(2000) default '' comment '返回参数', + status int(1) default 0 comment '操作状态(0正常 1异常)', + error_msg varchar(2000) default '' comment '错误消息', + oper_time datetime comment '操作时间', + cost_time bigint(20) default 0 comment '消耗时间', + primary key (oper_id), + key idx_sys_oper_log_bt (business_type), + key idx_sys_oper_log_s (status), + key idx_sys_oper_log_ot (oper_time) +) engine=innodb auto_increment=100 comment = '操作日志记录'; + + +-- ---------------------------- +-- 11、字典类型表 +-- ---------------------------- +drop table if exists sys_dict_type; +create table sys_dict_type +( + dict_id bigint(20) not null auto_increment comment '字典主键', + dict_name varchar(100) default '' comment '字典名称', + dict_type varchar(100) default '' comment '字典类型', + status char(1) default '0' comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (dict_id), + unique (dict_type) +) engine=innodb auto_increment=100 comment = '字典类型表'; + +insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', sysdate(), '', null, '用户性别列表'); +insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', sysdate(), '', null, '菜单状态列表'); +insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', sysdate(), '', null, '系统开关列表'); +insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', sysdate(), '', null, '任务状态列表'); +insert into sys_dict_type values(5, '任务分组', 'sys_job_group', '0', 'admin', sysdate(), '', null, '任务分组列表'); +insert into sys_dict_type values(6, '系统是否', 'sys_yes_no', '0', 'admin', sysdate(), '', null, '系统是否列表'); +insert into sys_dict_type values(7, '通知类型', 'sys_notice_type', '0', 'admin', sysdate(), '', null, '通知类型列表'); +insert into sys_dict_type values(8, '通知状态', 'sys_notice_status', '0', 'admin', sysdate(), '', null, '通知状态列表'); +insert into sys_dict_type values(9, '操作类型', 'sys_oper_type', '0', 'admin', sysdate(), '', null, '操作类型列表'); +insert into sys_dict_type values(10, '系统状态', 'sys_common_status', '0', 'admin', sysdate(), '', null, '登录状态列表'); + + +-- ---------------------------- +-- 12、字典数据表 +-- ---------------------------- +drop table if exists sys_dict_data; +create table sys_dict_data +( + dict_code bigint(20) not null auto_increment comment '字典编码', + dict_sort int(4) default 0 comment '字典排序', + dict_label varchar(100) default '' comment '字典标签', + dict_value varchar(100) default '' comment '字典键值', + dict_type varchar(100) default '' comment '字典类型', + css_class varchar(100) default null comment '样式属性(其他样式扩展)', + list_class varchar(100) default null comment '表格回显样式', + is_default char(1) default 'N' comment '是否默认(Y是 N否)', + status char(1) default '0' comment '状态(0正常 1停用)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (dict_code) +) engine=innodb auto_increment=100 comment = '字典数据表'; + +insert into sys_dict_data values(1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', sysdate(), '', null, '性别男'); +insert into sys_dict_data values(2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别女'); +insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别未知'); +insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '显示菜单'); +insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '隐藏菜单'); +insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); +insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); +insert into sys_dict_data values(10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', sysdate(), '', null, '默认分组'); +insert into sys_dict_data values(11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', sysdate(), '', null, '系统分组'); +insert into sys_dict_data values(12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '系统默认是'); +insert into sys_dict_data values(13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '系统默认否'); +insert into sys_dict_data values(14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', sysdate(), '', null, '通知'); +insert into sys_dict_data values(15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '公告'); +insert into sys_dict_data values(16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '关闭状态'); +insert into sys_dict_data values(18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '其他操作'); +insert into sys_dict_data values(19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '新增操作'); +insert into sys_dict_data values(20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '修改操作'); +insert into sys_dict_data values(21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '删除操作'); +insert into sys_dict_data values(22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '授权操作'); +insert into sys_dict_data values(23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导出操作'); +insert into sys_dict_data values(24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导入操作'); +insert into sys_dict_data values(25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '强退操作'); +insert into sys_dict_data values(26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '生成操作'); +insert into sys_dict_data values(27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '清空操作'); +insert into sys_dict_data values(28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '正常状态'); +insert into sys_dict_data values(29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); + + +-- ---------------------------- +-- 13、参数配置表 +-- ---------------------------- +drop table if exists sys_config; +create table sys_config ( + config_id int(5) not null auto_increment comment '参数主键', + config_name varchar(100) default '' comment '参数名称', + config_key varchar(100) default '' comment '参数键名', + config_value varchar(500) default '' comment '参数键值', + config_type char(1) default 'N' comment '系统内置(Y是 N否)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (config_id) +) engine=innodb auto_increment=100 comment = '参数配置表'; + +insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow' ); +insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456' ); +insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' ); +insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)'); +insert into sys_config values(5, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)'); + + +-- ---------------------------- +-- 14、系统访问记录 +-- ---------------------------- +drop table if exists sys_logininfor; +create table sys_logininfor ( + info_id bigint(20) not null auto_increment comment '访问ID', + user_name varchar(50) default '' comment '用户账号', + ipaddr varchar(128) default '' comment '登录IP地址', + status char(1) default '0' comment '登录状态(0成功 1失败)', + msg varchar(255) default '' comment '提示信息', + access_time datetime comment '访问时间', + primary key (info_id), + key idx_sys_logininfor_s (status), + key idx_sys_logininfor_lt (access_time) +) engine=innodb auto_increment=100 comment = '系统访问记录'; + + +-- ---------------------------- +-- 15、定时任务调度表 +-- ---------------------------- +drop table if exists sys_job; +create table sys_job ( + job_id bigint(20) not null auto_increment comment '任务ID', + job_name varchar(64) default '' comment '任务名称', + job_group varchar(64) default 'DEFAULT' comment '任务组名', + invoke_target varchar(500) not null comment '调用目标字符串', + cron_expression varchar(255) default '' comment 'cron执行表达式', + misfire_policy varchar(20) default '3' comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)', + concurrent char(1) default '1' comment '是否并发执行(0允许 1禁止)', + status char(1) default '0' comment '状态(0正常 1暂停)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default '' comment '备注信息', + primary key (job_id, job_name, job_group) +) engine=innodb auto_increment=100 comment = '定时任务调度表'; + +insert into sys_job values(1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); +insert into sys_job values(2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); +insert into sys_job values(3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); + + +-- ---------------------------- +-- 16、定时任务调度日志表 +-- ---------------------------- +drop table if exists sys_job_log; +create table sys_job_log ( + job_log_id bigint(20) not null auto_increment comment '任务日志ID', + job_name varchar(64) not null comment '任务名称', + job_group varchar(64) not null comment '任务组名', + invoke_target varchar(500) not null comment '调用目标字符串', + job_message varchar(500) comment '日志信息', + status char(1) default '0' comment '执行状态(0正常 1失败)', + exception_info varchar(2000) default '' comment '异常信息', + create_time datetime comment '创建时间', + primary key (job_log_id) +) engine=innodb comment = '定时任务调度日志表'; + + +-- ---------------------------- +-- 17、通知公告表 +-- ---------------------------- +drop table if exists sys_notice; +create table sys_notice ( + notice_id int(4) not null auto_increment comment '公告ID', + notice_title varchar(50) not null comment '公告标题', + notice_type char(1) not null comment '公告类型(1通知 2公告)', + notice_content longblob default null comment '公告内容', + status char(1) default '0' comment '公告状态(0正常 1关闭)', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(255) default null comment '备注', + primary key (notice_id) +) engine=innodb auto_increment=10 comment = '通知公告表'; + +-- ---------------------------- +-- 初始化-公告信息表数据 +-- ---------------------------- +insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员'); +insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员'); + + +-- ---------------------------- +-- 18、代码生成业务表 +-- ---------------------------- +drop table if exists gen_table; +create table gen_table ( + table_id bigint(20) not null auto_increment comment '编号', + table_name varchar(200) default '' comment '表名称', + table_comment varchar(500) default '' comment '表描述', + sub_table_name varchar(64) default null comment '关联子表的表名', + sub_table_fk_name varchar(64) default null comment '子表关联的外键名', + class_name varchar(100) default '' comment '实体类名称', + tpl_category varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作)', + package_name varchar(100) comment '生成包路径', + module_name varchar(30) comment '生成模块名', + business_name varchar(30) comment '生成业务名', + function_name varchar(50) comment '生成功能名', + function_author varchar(50) comment '生成功能作者', + gen_type char(1) default '0' comment '生成代码方式(0zip压缩包 1自定义路径)', + gen_path varchar(200) default '/' comment '生成路径(不填默认项目路径)', + options varchar(1000) comment '其它生成选项', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + remark varchar(500) default null comment '备注', + primary key (table_id) +) engine=innodb auto_increment=1 comment = '代码生成业务表'; + + +-- ---------------------------- +-- 19、代码生成业务表字段 +-- ---------------------------- +drop table if exists gen_table_column; +create table gen_table_column ( + column_id bigint(20) not null auto_increment comment '编号', + table_id varchar(64) comment '归属表编号', + column_name varchar(200) comment '列名称', + column_comment varchar(500) comment '列描述', + column_type varchar(100) comment '列类型', + java_type varchar(500) comment 'JAVA类型', + java_field varchar(200) comment 'JAVA字段名', + is_pk char(1) comment '是否主键(1是)', + is_increment char(1) comment '是否自增(1是)', + is_required char(1) comment '是否必填(1是)', + is_insert char(1) comment '是否为插入字段(1是)', + is_edit char(1) comment '是否编辑字段(1是)', + is_list char(1) comment '是否列表字段(1是)', + is_query char(1) comment '是否查询字段(1是)', + query_type varchar(200) default 'EQ' comment '查询方式(等于、不等于、大于、小于、范围)', + html_type varchar(200) comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)', + dict_type varchar(200) default '' comment '字典类型', + sort int comment '排序', + create_by varchar(64) default '' comment '创建者', + create_time datetime comment '创建时间', + update_by varchar(64) default '' comment '更新者', + update_time datetime comment '更新时间', + primary key (column_id) +) engine=innodb auto_increment=1 comment = '代码生成业务表字段'; diff --git a/docsql/分库分表/ry_seata_20210128.sql b/docsql/分库分表/ry_seata_20210128.sql new file mode 100644 index 00000000..41163c1b --- /dev/null +++ b/docsql/分库分表/ry_seata_20210128.sql @@ -0,0 +1,80 @@ +DROP DATABASE IF EXISTS `ry-seata`; + +CREATE DATABASE `ry-seata` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +USE `ry-seata`; + +-- -------------------------------- The script used when storeMode is 'db' -------------------------------- +-- the table to store GlobalSession data +CREATE TABLE IF NOT EXISTS `global_table` +( + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `status` TINYINT NOT NULL, + `application_id` VARCHAR(32), + `transaction_service_group` VARCHAR(32), + `transaction_name` VARCHAR(128), + `timeout` INT, + `begin_time` BIGINT, + `application_data` VARCHAR(2000), + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`xid`), + KEY `idx_gmt_modified_status` (`gmt_modified`, `status`), + KEY `idx_transaction_id` (`transaction_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store BranchSession data +CREATE TABLE IF NOT EXISTS `branch_table` +( + `branch_id` BIGINT NOT NULL, + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `resource_group_id` VARCHAR(32), + `resource_id` VARCHAR(256), + `branch_type` VARCHAR(8), + `status` TINYINT, + `client_id` VARCHAR(64), + `application_data` VARCHAR(2000), + `gmt_create` DATETIME(6), + `gmt_modified` DATETIME(6), + PRIMARY KEY (`branch_id`), + KEY `idx_xid` (`xid`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store lock data +CREATE TABLE IF NOT EXISTS `lock_table` +( + `row_key` VARCHAR(128) NOT NULL, + `xid` VARCHAR(96), + `transaction_id` BIGINT, + `branch_id` BIGINT NOT NULL, + `resource_id` VARCHAR(256), + `table_name` VARCHAR(32), + `pk` VARCHAR(36), + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`row_key`), + KEY `idx_branch_id` (`branch_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- for AT mode you must to init this sql for you business database. the seata server not need it. +CREATE TABLE IF NOT EXISTS `undo_log` +( + `branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id', + `xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id', + `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', + `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', + `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', + UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table'; \ No newline at end of file diff --git a/docsql/分库分表/seata_account.sql b/docsql/分库分表/seata_account.sql new file mode 100644 index 00000000..3c1ed459 --- /dev/null +++ b/docsql/分库分表/seata_account.sql @@ -0,0 +1,57 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80011 + Source Host : localhost:3306 + Source Schema : seata_account + + Target Server Type : MySQL + Target Server Version : 80011 + File Encoding : 65001 + + Date: 11/03/2023 15:26:35 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for account +-- ---------------------------- +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `balance` double NULL DEFAULT NULL, + `last_update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of account +-- ---------------------------- +INSERT INTO `account` VALUES (1, 40, '2023-03-11 12:06:48'); + +-- ---------------------------- +-- Table structure for undo_log +-- ---------------------------- +DROP TABLE IF EXISTS `undo_log`; +CREATE TABLE `undo_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `context` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime NOT NULL, + `log_modified` datetime NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of undo_log +-- ---------------------------- + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/docsql/分库分表/seata_order.sql b/docsql/分库分表/seata_order.sql new file mode 100644 index 00000000..0cb981d0 --- /dev/null +++ b/docsql/分库分表/seata_order.sql @@ -0,0 +1,62 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80011 + Source Host : localhost:3306 + Source Schema : seata_order + + Target Server Type : MySQL + Target Server Version : 80011 + File Encoding : 65001 + + Date: 11/03/2023 15:27:04 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for p_order +-- ---------------------------- +DROP TABLE IF EXISTS `p_order`; +CREATE TABLE `p_order` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NULL DEFAULT NULL, + `product_id` int(11) NULL DEFAULT NULL, + `amount` int(11) NULL DEFAULT NULL, + `total_price` double NULL DEFAULT NULL, + `status` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `add_time` datetime NULL DEFAULT CURRENT_TIMESTAMP, + `last_update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of p_order +-- ---------------------------- +INSERT INTO `p_order` VALUES (4, 1, 1, 1, 10, '1', '2023-03-11 12:06:48', '2023-03-11 12:06:48'); + +-- ---------------------------- +-- Table structure for undo_log +-- ---------------------------- +DROP TABLE IF EXISTS `undo_log`; +CREATE TABLE `undo_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `context` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime NOT NULL, + `log_modified` datetime NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of undo_log +-- ---------------------------- + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/docsql/分库分表/seata_product.sql b/docsql/分库分表/seata_product.sql new file mode 100644 index 00000000..d38e040d --- /dev/null +++ b/docsql/分库分表/seata_product.sql @@ -0,0 +1,58 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80011 + Source Host : localhost:3306 + Source Schema : seata_product + + Target Server Type : MySQL + Target Server Version : 80011 + File Encoding : 65001 + + Date: 11/03/2023 15:27:11 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for product +-- ---------------------------- +DROP TABLE IF EXISTS `product`; +CREATE TABLE `product` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `price` double NULL DEFAULT NULL, + `stock` int(11) NULL DEFAULT NULL, + `last_update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of product +-- ---------------------------- +INSERT INTO `product` VALUES (1, 10, 18, '2023-03-11 12:06:48'); + +-- ---------------------------- +-- Table structure for undo_log +-- ---------------------------- +DROP TABLE IF EXISTS `undo_log`; +CREATE TABLE `undo_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `context` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime NOT NULL, + `log_modified` datetime NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of undo_log +-- ---------------------------- + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..015e8c07 --- /dev/null +++ b/pom.xml @@ -0,0 +1,331 @@ + + + 4.0.0 + + com.yanzhu + yanzhu + 3.6.2 + + yanzhu + http://www.sxyanzhu.com + 研筑微服务系统 + + + 3.6.2 + UTF-8 + UTF-8 + 1.8 + 2.7.7 + 2021.0.5 + 2021.0.4.0 + 2.7.10 + 3.0.0 + 1.6.2 + 1.27.2 + 2.3.3 + 1.4.6 + 1.2.16 + 3.5.2 + 2.11.0 + 2.3 + 2.0.23 + 0.9.1 + 8.2.2 + 4.1.2 + 2.14.2 + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + com.github.tobato + fastdfs-client + ${tobato.version} + + + + + io.swagger + swagger-models + ${swagger.core.version} + + + io.swagger + swagger-annotations + ${swagger.core.version} + + + + + pro.fessional + kaptcha + ${kaptcha.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + commons-io + commons-io + ${commons.io.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + + + com.alibaba + transmittable-thread-local + ${transmittable-thread-local.version} + + + + + com.yanzhu + yanzhu-common-core + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-swagger + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-security + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-datascope + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-datasource + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-seata + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-log + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-common-redis + ${yanzhu.version} + + + + + com.yanzhu + yanzhu-api-system + ${yanzhu.version} + + + + + + + yanzhu-api + yanzhu-common + yanzhu-auth + yanzhu-gateway + yanzhu-modules + yanzhu-monitor + yanzhu-rocketmq + yanzhu-modules/yanzhu-wechat + yanzhu-modules/yanzhu-manage + + pom + + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public + + true + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public + + true + + + false + + + + + + + + 本地服务器环境 + + + 本地服务器环境 + 62.234.3.186:8848 + + + + true + + + + 线上服务器环境 + + 线上服务器环境 + 0.0.0.0:8848 + + + + 测试服务器环境 + + 测试服务器环境 + 62.234.3.186:8848 + + + + + docker测试环境1 + + docker测试环境1 + http://0.0.0.0:5001 + + + + docker测试环境2 + + docker测试环境2 + http://0.0.0.0:5001 + + + + + \ No newline at end of file diff --git a/yanzhu-api/pom.xml b/yanzhu-api/pom.xml new file mode 100644 index 00000000..47ec57cf --- /dev/null +++ b/yanzhu-api/pom.xml @@ -0,0 +1,22 @@ + + + + com.yanzhu + yanzhu + 3.6.2 + + 4.0.0 + + + yanzhu-api-system + + + yanzhu-api + pom + + + yanzhu-api系统接口 + + + diff --git a/yanzhu-api/yanzhu-api-system/pom.xml b/yanzhu-api/yanzhu-api-system/pom.xml new file mode 100644 index 00000000..be9fb913 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/pom.xml @@ -0,0 +1,28 @@ + + + + com.yanzhu + yanzhu-api + 3.6.2 + + 4.0.0 + + yanzhu-api-system + + + yanzhu-api-system系统接口模块 + + + + + + + com.yanzhu + yanzhu-common-core + + + + + \ No newline at end of file diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteFileService.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteFileService.java new file mode 100644 index 00000000..1a736406 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteFileService.java @@ -0,0 +1,29 @@ +package com.yanzhu.system.api; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import com.yanzhu.common.core.constant.ServiceNameConstants; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysFile; +import com.yanzhu.system.api.factory.RemoteFileFallbackFactory; + +/** + * 文件服务 + * + * @author ruoyi + */ +@FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.FILE_SERVICE, fallbackFactory = RemoteFileFallbackFactory.class) +public interface RemoteFileService +{ + /** + * 上传文件 + * + * @param file 文件信息 + * @return 结果 + */ + @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R upload(@RequestPart(value = "file") MultipartFile file); +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteLogService.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteLogService.java new file mode 100644 index 00000000..db9a5ecd --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteLogService.java @@ -0,0 +1,41 @@ +package com.yanzhu.system.api; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.ServiceNameConstants; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysLogininfor; +import com.yanzhu.system.api.domain.SysOperLog; +import com.yanzhu.system.api.factory.RemoteLogFallbackFactory; + +/** + * 日志服务 + * + * @author ruoyi + */ +@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class) +public interface RemoteLogService +{ + /** + * 保存系统日志 + * + * @param sysOperLog 日志实体 + * @param source 请求来源 + * @return 结果 + */ + @PostMapping("/operlog") + public R saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + /** + * 保存访问记录 + * + * @param sysLogininfor 访问实体 + * @param source 请求来源 + * @return 结果 + */ + @PostMapping("/logininfor") + public R saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteUserService.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteUserService.java new file mode 100644 index 00000000..e57c9a85 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/RemoteUserService.java @@ -0,0 +1,43 @@ +package com.yanzhu.system.api; + +import com.yanzhu.system.api.model.LoginUser; +import org.springframework.cloud.openfeign.FeignClient; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.ServiceNameConstants; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.api.factory.RemoteUserFallbackFactory; + +/** + * 用户服务 + * + * @author ruoyi + */ +@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class) +public interface RemoteUserService +{ + /** + * 通过用户名查询用户信息 + * + * @param username 用户名 + * @param source 请求来源 + * @return 结果 + */ + @GetMapping("/user/info/{username}") + public R getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + /** + * 注册用户信息 + * + * @param sysUser 用户信息 + * @param source 请求来源 + * @return 结果 + */ + @PostMapping("/user/register") + public R registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDept.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDept.java new file mode 100644 index 00000000..a7d571d4 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDept.java @@ -0,0 +1,203 @@ +package com.yanzhu.system.api.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 部门表 sys_dept + * + * @author ruoyi + */ +public class SysDept extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 部门ID */ + private Long deptId; + + /** 父部门ID */ + private Long parentId; + + /** 祖级列表 */ + private String ancestors; + + /** 部门名称 */ + private String deptName; + + /** 显示顺序 */ + private Integer orderNum; + + /** 负责人 */ + private String leader; + + /** 联系电话 */ + private String phone; + + /** 邮箱 */ + private String email; + + /** 部门状态:0正常,1停用 */ + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 父部门名称 */ + private String parentName; + + /** 子部门 */ + private List children = new ArrayList(); + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + @NotBlank(message = "部门名称不能为空") + @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getLeader() + { + return leader; + } + + public void setLeader(String leader) + { + this.leader = leader; + } + + @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") + public String getPhone() + { + return phone; + } + + public void setPhone(String phone) + { + this.phone = phone; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("deptId", getDeptId()) + .append("parentId", getParentId()) + .append("ancestors", getAncestors()) + .append("deptName", getDeptName()) + .append("orderNum", getOrderNum()) + .append("leader", getLeader()) + .append("phone", getPhone()) + .append("email", getEmail()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictData.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictData.java new file mode 100644 index 00000000..a9f288c5 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictData.java @@ -0,0 +1,176 @@ +package com.yanzhu.system.api.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 字典数据表 sys_dict_data + * + * @author ruoyi + */ +public class SysDictData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典编码 */ + @Excel(name = "字典编码", cellType = ColumnType.NUMERIC) + private Long dictCode; + + /** 字典排序 */ + @Excel(name = "字典排序", cellType = ColumnType.NUMERIC) + private Long dictSort; + + /** 字典标签 */ + @Excel(name = "字典标签") + private String dictLabel; + + /** 字典键值 */ + @Excel(name = "字典键值") + private String dictValue; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 样式属性(其他样式扩展) */ + private String cssClass; + + /** 表格字典样式 */ + private String listClass; + + /** 是否默认(Y是 N否) */ + @Excel(name = "是否默认", readConverterExp = "Y=是,N=否") + private String isDefault; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictCode() + { + return dictCode; + } + + public void setDictCode(Long dictCode) + { + this.dictCode = dictCode; + } + + public Long getDictSort() + { + return dictSort; + } + + public void setDictSort(Long dictSort) + { + this.dictSort = dictSort; + } + + @NotBlank(message = "字典标签不能为空") + @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") + public String getDictLabel() + { + return dictLabel; + } + + public void setDictLabel(String dictLabel) + { + this.dictLabel = dictLabel; + } + + @NotBlank(message = "字典键值不能为空") + @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") + public String getDictValue() + { + return dictValue; + } + + public void setDictValue(String dictValue) + { + this.dictValue = dictValue; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") + public String getCssClass() + { + return cssClass; + } + + public void setCssClass(String cssClass) + { + this.cssClass = cssClass; + } + + public String getListClass() + { + return listClass; + } + + public void setListClass(String listClass) + { + this.listClass = listClass; + } + + public boolean getDefault() + { + return UserConstants.YES.equals(this.isDefault); + } + + public String getIsDefault() + { + return isDefault; + } + + public void setIsDefault(String isDefault) + { + this.isDefault = isDefault; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictCode", getDictCode()) + .append("dictSort", getDictSort()) + .append("dictLabel", getDictLabel()) + .append("dictValue", getDictValue()) + .append("dictType", getDictType()) + .append("cssClass", getCssClass()) + .append("listClass", getListClass()) + .append("isDefault", getIsDefault()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictType.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictType.java new file mode 100644 index 00000000..418bcdbf --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysDictType.java @@ -0,0 +1,96 @@ +package com.yanzhu.system.api.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 字典类型表 sys_dict_type + * + * @author ruoyi + */ +public class SysDictType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典主键 */ + @Excel(name = "字典主键", cellType = ColumnType.NUMERIC) + private Long dictId; + + /** 字典名称 */ + @Excel(name = "字典名称") + private String dictName; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictId() + { + return dictId; + } + + public void setDictId(Long dictId) + { + this.dictId = dictId; + } + + @NotBlank(message = "字典名称不能为空") + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") + public String getDictName() + { + return dictName; + } + + public void setDictName(String dictName) + { + this.dictName = dictName; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictId", getDictId()) + .append("dictName", getDictName()) + .append("dictType", getDictType()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysFile.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysFile.java new file mode 100644 index 00000000..14eab512 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysFile.java @@ -0,0 +1,50 @@ +package com.yanzhu.system.api.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 文件信息 + * + * @author ruoyi + */ +public class SysFile +{ + /** + * 文件名称 + */ + private String name; + + /** + * 文件地址 + */ + private String url; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("name", getName()) + .append("url", getUrl()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysLogininfor.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysLogininfor.java new file mode 100644 index 00000000..e5f885f6 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysLogininfor.java @@ -0,0 +1,102 @@ +package com.yanzhu.system.api.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 系统访问记录表 sys_logininfor + * + * @author ruoyi + */ +public class SysLogininfor extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "序号", cellType = ColumnType.NUMERIC) + private Long infoId; + + /** 用户账号 */ + @Excel(name = "用户账号") + private String userName; + + /** 状态 0成功 1失败 */ + @Excel(name = "状态", readConverterExp = "0=成功,1=失败") + private String status; + + /** 地址 */ + @Excel(name = "地址") + private String ipaddr; + + /** 描述 */ + @Excel(name = "描述") + private String msg; + + /** 访问时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date accessTime; + + public Long getInfoId() + { + return infoId; + } + + public void setInfoId(Long infoId) + { + this.infoId = infoId; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public Date getAccessTime() + { + return accessTime; + } + + public void setAccessTime(Date accessTime) + { + this.accessTime = accessTime; + } +} \ No newline at end of file diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysOperLog.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysOperLog.java new file mode 100644 index 00000000..d34180e1 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysOperLog.java @@ -0,0 +1,255 @@ +package com.yanzhu.system.api.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 操作日志记录表 oper_log + * + * @author ruoyi + */ +public class SysOperLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 日志主键 */ + @Excel(name = "操作序号", cellType = ColumnType.NUMERIC) + private Long operId; + + /** 操作模块 */ + @Excel(name = "操作模块") + private String title; + + /** 业务类型(0其它 1新增 2修改 3删除) */ + @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据") + private Integer businessType; + + /** 业务类型数组 */ + private Integer[] businessTypes; + + /** 请求方法 */ + @Excel(name = "请求方法") + private String method; + + /** 请求方式 */ + @Excel(name = "请求方式") + private String requestMethod; + + /** 操作类别(0其它 1后台用户 2手机端用户) */ + @Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户") + private Integer operatorType; + + /** 操作人员 */ + @Excel(name = "操作人员") + private String operName; + + /** 部门名称 */ + @Excel(name = "部门名称") + private String deptName; + + /** 请求url */ + @Excel(name = "请求地址") + private String operUrl; + + /** 操作地址 */ + @Excel(name = "操作地址") + private String operIp; + + /** 请求参数 */ + @Excel(name = "请求参数") + private String operParam; + + /** 返回参数 */ + @Excel(name = "返回参数") + private String jsonResult; + + /** 操作状态(0正常 1异常) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=异常") + private Integer status; + + /** 错误消息 */ + @Excel(name = "错误消息") + private String errorMsg; + + /** 操作时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date operTime; + + /** 消耗时间 */ + @Excel(name = "消耗时间", suffix = "毫秒") + private Long costTime; + + public Long getOperId() + { + return operId; + } + + public void setOperId(Long operId) + { + this.operId = operId; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public Integer getBusinessType() + { + return businessType; + } + + public void setBusinessType(Integer businessType) + { + this.businessType = businessType; + } + + public Integer[] getBusinessTypes() + { + return businessTypes; + } + + public void setBusinessTypes(Integer[] businessTypes) + { + this.businessTypes = businessTypes; + } + + public String getMethod() + { + return method; + } + + public void setMethod(String method) + { + this.method = method; + } + + public String getRequestMethod() + { + return requestMethod; + } + + public void setRequestMethod(String requestMethod) + { + this.requestMethod = requestMethod; + } + + public Integer getOperatorType() + { + return operatorType; + } + + public void setOperatorType(Integer operatorType) + { + this.operatorType = operatorType; + } + + public String getOperName() + { + return operName; + } + + public void setOperName(String operName) + { + this.operName = operName; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getOperUrl() + { + return operUrl; + } + + public void setOperUrl(String operUrl) + { + this.operUrl = operUrl; + } + + public String getOperIp() + { + return operIp; + } + + public void setOperIp(String operIp) + { + this.operIp = operIp; + } + + public String getOperParam() + { + return operParam; + } + + public void setOperParam(String operParam) + { + this.operParam = operParam; + } + + public String getJsonResult() + { + return jsonResult; + } + + public void setJsonResult(String jsonResult) + { + this.jsonResult = jsonResult; + } + + public Integer getStatus() + { + return status; + } + + public void setStatus(Integer status) + { + this.status = status; + } + + public String getErrorMsg() + { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) + { + this.errorMsg = errorMsg; + } + + public Date getOperTime() + { + return operTime; + } + + public void setOperTime(Date operTime) + { + this.operTime = operTime; + } + + public Long getCostTime() + { + return costTime; + } + + public void setCostTime(Long costTime) + { + this.costTime = costTime; + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysRole.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysRole.java new file mode 100644 index 00000000..afaf1e03 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysRole.java @@ -0,0 +1,241 @@ +package com.yanzhu.system.api.domain; + +import java.util.Set; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 角色表 sys_role + * + * @author ruoyi + */ +public class SysRole extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 角色ID */ + @Excel(name = "角色序号", cellType = ColumnType.NUMERIC) + private Long roleId; + + /** 角色名称 */ + @Excel(name = "角色名称") + private String roleName; + + /** 角色权限 */ + @Excel(name = "角色权限") + private String roleKey; + + /** 角色排序 */ + @Excel(name = "角色排序") + private Integer roleSort; + + /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ + @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") + private String dataScope; + + /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ + private boolean menuCheckStrictly; + + /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ + private boolean deptCheckStrictly; + + /** 角色状态(0正常 1停用) */ + @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 用户是否存在此角色标识 默认不存在 */ + private boolean flag = false; + + /** 菜单组 */ + private Long[] menuIds; + + /** 部门组(数据权限) */ + private Long[] deptIds; + + /** 角色菜单权限 */ + private Set permissions; + + public SysRole() + { + + } + + public SysRole(Long roleId) + { + this.roleId = roleId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public boolean isAdmin() + { + return isAdmin(this.roleId); + } + + public static boolean isAdmin(Long roleId) + { + return roleId != null && 1L == roleId; + } + + @NotBlank(message = "角色名称不能为空") + @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") + public String getRoleName() + { + return roleName; + } + + public void setRoleName(String roleName) + { + this.roleName = roleName; + } + + @NotBlank(message = "权限字符不能为空") + @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") + public String getRoleKey() + { + return roleKey; + } + + public void setRoleKey(String roleKey) + { + this.roleKey = roleKey; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getRoleSort() + { + return roleSort; + } + + public void setRoleSort(Integer roleSort) + { + this.roleSort = roleSort; + } + + public String getDataScope() + { + return dataScope; + } + + public void setDataScope(String dataScope) + { + this.dataScope = dataScope; + } + + public boolean isMenuCheckStrictly() + { + return menuCheckStrictly; + } + + public void setMenuCheckStrictly(boolean menuCheckStrictly) + { + this.menuCheckStrictly = menuCheckStrictly; + } + + public boolean isDeptCheckStrictly() + { + return deptCheckStrictly; + } + + public void setDeptCheckStrictly(boolean deptCheckStrictly) + { + this.deptCheckStrictly = deptCheckStrictly; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + public Long[] getMenuIds() + { + return menuIds; + } + + public void setMenuIds(Long[] menuIds) + { + this.menuIds = menuIds; + } + + public Long[] getDeptIds() + { + return deptIds; + } + + public void setDeptIds(Long[] deptIds) + { + this.deptIds = deptIds; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("roleName", getRoleName()) + .append("roleKey", getRoleKey()) + .append("roleSort", getRoleSort()) + .append("dataScope", getDataScope()) + .append("menuCheckStrictly", isMenuCheckStrictly()) + .append("deptCheckStrictly", isDeptCheckStrictly()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysUser.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysUser.java new file mode 100644 index 00000000..3c0fe041 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/domain/SysUser.java @@ -0,0 +1,323 @@ +package com.yanzhu.system.api.domain; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.*; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.annotation.Excel.Type; +import com.yanzhu.common.core.annotation.Excels; +import com.yanzhu.common.core.web.domain.BaseEntity; +import com.yanzhu.common.core.xss.Xss; + +/** + * 用户对象 sys_user + * + * @author ruoyi + */ +public class SysUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户ID */ + @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") + private Long userId; + + /** 部门ID */ + @Excel(name = "部门编号", type = Type.IMPORT) + private Long deptId; + + /** 用户账号 */ + @Excel(name = "登录名称") + private String userName; + + /** 用户昵称 */ + @Excel(name = "用户名称") + private String nickName; + + /** 用户邮箱 */ + @Excel(name = "用户邮箱") + private String email; + + /** 手机号码 */ + @Excel(name = "手机号码") + private String phonenumber; + + /** 用户性别 */ + @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") + private String sex; + + /** 用户头像 */ + private String avatar; + + /** 密码 */ + private String password; + + /** 帐号状态(0正常 1停用) */ + @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 最后登录IP */ + @Excel(name = "最后登录IP", type = Type.EXPORT) + private String loginIp; + + /** 最后登录时间 */ + @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) + private Date loginDate; + + /** 部门对象 */ + @Excels({ + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + }) + private SysDept dept; + + /** 角色对象 */ + private List roles; + + /** 角色组 */ + private Long[] roleIds; + + /** 岗位组 */ + private Long[] postIds; + + /** 角色ID */ + private Long roleId; + + public SysUser() + { + + } + + public SysUser(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public boolean isAdmin() + { + return isAdmin(this.userId); + } + + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Xss(message = "用户昵称不能包含脚本字符") + @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @Xss(message = "用户账号不能包含脚本字符") + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") + public String getPhonenumber() + { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) + { + this.phonenumber = phonenumber; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getLoginIp() + { + return loginIp; + } + + public void setLoginIp(String loginIp) + { + this.loginIp = loginIp; + } + + public Date getLoginDate() + { + return loginDate; + } + + public void setLoginDate(Date loginDate) + { + this.loginDate = loginDate; + } + + public SysDept getDept() + { + return dept; + } + + public void setDept(SysDept dept) + { + this.dept = dept; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + public Long[] getRoleIds() + { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) + { + this.roleIds = roleIds; + } + + public Long[] getPostIds() + { + return postIds; + } + + public void setPostIds(Long[] postIds) + { + this.postIds = postIds; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + @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("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .toString(); + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteFileFallbackFactory.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteFileFallbackFactory.java new file mode 100644 index 00000000..60cce79b --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteFileFallbackFactory.java @@ -0,0 +1,35 @@ +package com.yanzhu.system.api.factory; + +import com.yanzhu.system.api.RemoteFileService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysFile; + +/** + * 文件服务降级处理 + * + * @author ruoyi + */ +@Component +public class RemoteFileFallbackFactory implements FallbackFactory +{ + private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class); + + @Override + public RemoteFileService create(Throwable throwable) + { + log.error("文件服务调用失败:{}", throwable.getMessage()); + return new RemoteFileService() + { + @Override + public R upload(MultipartFile file) + { + return R.fail("上传文件失败:" + throwable.getMessage()); + } + }; + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteLogFallbackFactory.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteLogFallbackFactory.java new file mode 100644 index 00000000..1a848bde --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteLogFallbackFactory.java @@ -0,0 +1,42 @@ +package com.yanzhu.system.api.factory; + +import com.yanzhu.system.api.RemoteLogService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysLogininfor; +import com.yanzhu.system.api.domain.SysOperLog; + +/** + * 日志服务降级处理 + * + * @author ruoyi + */ +@Component +public class RemoteLogFallbackFactory implements FallbackFactory +{ + private static final Logger log = LoggerFactory.getLogger(RemoteLogFallbackFactory.class); + + @Override + public RemoteLogService create(Throwable throwable) + { + log.error("日志服务调用失败:{}", throwable.getMessage()); + return new RemoteLogService() + { + @Override + public R saveLog(SysOperLog sysOperLog, String source) + { + return null; + } + + @Override + public R saveLogininfor(SysLogininfor sysLogininfor, String source) + { + return null; + } + }; + + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteUserFallbackFactory.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteUserFallbackFactory.java new file mode 100644 index 00000000..bca69663 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/factory/RemoteUserFallbackFactory.java @@ -0,0 +1,41 @@ +package com.yanzhu.system.api.factory; + +import com.yanzhu.system.api.RemoteUserService; +import com.yanzhu.system.api.model.LoginUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.system.api.domain.SysUser; + +/** + * 用户服务降级处理 + * + * @author ruoyi + */ +@Component +public class RemoteUserFallbackFactory implements FallbackFactory +{ + private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class); + + @Override + public RemoteUserService create(Throwable throwable) + { + log.error("用户服务调用失败:{}", throwable.getMessage()); + return new RemoteUserService() + { + @Override + public R getUserInfo(String username, String source) + { + return R.fail("获取用户失败:" + throwable.getMessage()); + } + + @Override + public R registerUserInfo(SysUser sysUser, String source) + { + return R.fail("注册用户失败:" + throwable.getMessage()); + } + }; + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/model/LoginUser.java b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/model/LoginUser.java new file mode 100644 index 00000000..30e41ae9 --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/java/com/yanzhu/system/api/model/LoginUser.java @@ -0,0 +1,150 @@ +package com.yanzhu.system.api.model; + +import java.io.Serializable; +import java.util.Set; +import com.yanzhu.system.api.domain.SysUser; + +/** + * 用户信息 + * + * @author ruoyi + */ +public class LoginUser implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 用户名id + */ + private Long userid; + + /** + * 用户名 + */ + private String username; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 权限列表 + */ + private Set permissions; + + /** + * 角色列表 + */ + private Set roles; + + /** + * 用户信息 + */ + private SysUser sysUser; + + public String getToken() + { + return token; + } + + public void setToken(String token) + { + this.token = token; + } + + public Long getUserid() + { + return userid; + } + + public void setUserid(Long userid) + { + this.userid = userid; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } + + public Long getExpireTime() + { + return expireTime; + } + + public void setExpireTime(Long expireTime) + { + this.expireTime = expireTime; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + public Set getRoles() + { + return roles; + } + + public void setRoles(Set roles) + { + this.roles = roles; + } + + public SysUser getSysUser() + { + return sysUser; + } + + public void setSysUser(SysUser sysUser) + { + this.sysUser = sysUser; + } +} diff --git a/yanzhu-api/yanzhu-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-api/yanzhu-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..30145fdc --- /dev/null +++ b/yanzhu-api/yanzhu-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,3 @@ +com.yanzhu.system.api.factory.RemoteUserFallbackFactory +com.yanzhu.system.api.factory.RemoteLogFallbackFactory +com.yanzhu.system.api.factory.RemoteFileFallbackFactory diff --git a/yanzhu-auth/pom.xml b/yanzhu-auth/pom.xml new file mode 100644 index 00000000..7fb1ba72 --- /dev/null +++ b/yanzhu-auth/pom.xml @@ -0,0 +1,117 @@ + + + com.yanzhu + yanzhu + 3.6.2 + + 4.0.0 + + yanzhu-auth + + + yanzhu-auth认证授权中心 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.yanzhu + yanzhu-common-security + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/RuoYiAuthApplication.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/RuoYiAuthApplication.java new file mode 100644 index 00000000..3bdb03e4 --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/RuoYiAuthApplication.java @@ -0,0 +1,31 @@ +package com.yanzhu.auth; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; + +/** + * 认证授权中心 + * + * @author ruoyi + */ +@EnableRyFeignClients +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) +public class RuoYiAuthApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiAuthApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/controller/TokenController.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/controller/TokenController.java new file mode 100644 index 00000000..768b975b --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/controller/TokenController.java @@ -0,0 +1,78 @@ +package com.yanzhu.auth.controller; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import com.yanzhu.auth.form.LoginBody; +import com.yanzhu.auth.form.RegisterBody; +import com.yanzhu.auth.service.SysLoginService; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.utils.JwtUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.auth.AuthUtil; +import com.yanzhu.common.security.service.TokenService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.model.LoginUser; + +/** + * token 控制 + * + * @author ruoyi + */ +@RestController +public class TokenController +{ + @Autowired + private TokenService tokenService; + + @Autowired + private SysLoginService sysLoginService; + + @PostMapping("login") + public R login(@RequestBody LoginBody form) + { + // 用户登录 + LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword()); + // 获取登录token + return R.ok(tokenService.createToken(userInfo)); + } + + @DeleteMapping("logout") + public R logout(HttpServletRequest request) + { + String token = SecurityUtils.getToken(request); + if (StringUtils.isNotEmpty(token)) + { + String username = JwtUtils.getUserName(token); + // 删除用户缓存记录 + AuthUtil.logoutByToken(token); + // 记录用户退出日志 + sysLoginService.logout(username); + } + return R.ok(); + } + + @PostMapping("refresh") + public R refresh(HttpServletRequest request) + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser)) + { + // 刷新令牌有效期 + tokenService.refreshToken(loginUser); + return R.ok(); + } + return R.ok(); + } + + @PostMapping("register") + public R register(@RequestBody RegisterBody registerBody) + { + // 用户注册 + sysLoginService.register(registerBody.getUsername(), registerBody.getPassword()); + return R.ok(); + } +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/form/LoginBody.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/form/LoginBody.java new file mode 100644 index 00000000..094063d4 --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/form/LoginBody.java @@ -0,0 +1,39 @@ +package com.yanzhu.auth.form; + +/** + * 用户登录对象 + * + * @author ruoyi + */ +public class LoginBody +{ + /** + * 用户名 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + 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; + } +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/form/RegisterBody.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/form/RegisterBody.java new file mode 100644 index 00000000..2cb5bc37 --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/form/RegisterBody.java @@ -0,0 +1,11 @@ +package com.yanzhu.auth.form; + +/** + * 用户注册对象 + * + * @author ruoyi + */ +public class RegisterBody extends LoginBody +{ + +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysLoginService.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysLoginService.java new file mode 100644 index 00000000..3bae6fc0 --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysLoginService.java @@ -0,0 +1,143 @@ +package com.yanzhu.auth.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.enums.UserStatus; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.ip.IpUtils; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.RemoteUserService; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.api.model.LoginUser; + +/** + * 登录校验方法 + * + * @author ruoyi + */ +@Component +public class SysLoginService +{ + @Autowired + private RemoteUserService remoteUserService; + + @Autowired + private SysPasswordService passwordService; + + @Autowired + private SysRecordLogService recordLogService; + + @Autowired + private RedisService redisService; + + /** + * 登录 + */ + public LoginUser login(String username, String password) + { + // 用户名或密码为空 错误 + if (StringUtils.isAnyBlank(username, password)) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); + throw new ServiceException("用户/密码必须填写"); + } + // 密码如果不在指定范围内 错误 + if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); + throw new ServiceException("用户密码不在指定范围"); + } + // 用户名不在指定范围内 错误 + if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); + throw new ServiceException("用户名不在指定范围"); + } + // IP黑名单校验 + String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); + if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单"); + throw new ServiceException("很遗憾,访问IP已被列入系统黑名单"); + } + // 查询用户信息 + R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); + + if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); + throw new ServiceException("登录用户:" + username + " 不存在"); + } + + if (R.FAIL == userResult.getCode()) + { + throw new ServiceException(userResult.getMsg()); + } + + LoginUser userInfo = userResult.getData(); + SysUser user = userResult.getData().getSysUser(); + if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } + if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + passwordService.validate(user, password); + recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); + return userInfo; + } + + public void logout(String loginName) + { + recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); + } + + /** + * 注册 + */ + public void register(String username, String password) + { + // 用户名或密码为空 错误 + if (StringUtils.isAnyBlank(username, password)) + { + throw new ServiceException("用户/密码必须填写"); + } + if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + throw new ServiceException("账户长度必须在2到20个字符之间"); + } + if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + throw new ServiceException("密码长度必须在5到20个字符之间"); + } + + // 注册用户信息 + SysUser sysUser = new SysUser(); + sysUser.setUserName(username); + sysUser.setNickName(username); + sysUser.setPassword(SecurityUtils.encryptPassword(password)); + R registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); + + if (R.FAIL == registerResult.getCode()) + { + throw new ServiceException(registerResult.getMsg()); + } + recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功"); + } +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysPasswordService.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysPasswordService.java new file mode 100644 index 00000000..d352e406 --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysPasswordService.java @@ -0,0 +1,85 @@ +package com.yanzhu.auth.service; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysUser; + +/** + * 登录密码方法 + * + * @author ruoyi + */ +@Component +public class SysPasswordService +{ + @Autowired + private RedisService redisService; + + private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT; + + private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME; + + @Autowired + private SysRecordLogService recordLogService; + + /** + * 登录账户密码错误次数缓存键名 + * + * @param username 用户名 + * @return 缓存键key + */ + private String getCacheKey(String username) + { + return CacheConstants.PWD_ERR_CNT_KEY + username; + } + + public void validate(SysUser user, String password) + { + String username = user.getUserName(); + + Integer retryCount = redisService.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL,errMsg); + throw new ServiceException(errMsg); + } + + if (!matches(user, password)) + { + retryCount = retryCount + 1; + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", retryCount)); + redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new ServiceException("用户不存在/密码错误"); + } + else + { + clearLoginRecordCache(username); + } + } + + public boolean matches(SysUser user, String rawPassword) + { + return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); + } + + public void clearLoginRecordCache(String loginName) + { + if (redisService.hasKey(getCacheKey(loginName))) + { + redisService.deleteObject(getCacheKey(loginName)); + } + } +} diff --git a/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysRecordLogService.java b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysRecordLogService.java new file mode 100644 index 00000000..c505932c --- /dev/null +++ b/yanzhu-auth/src/main/java/com/yanzhu/auth/service/SysRecordLogService.java @@ -0,0 +1,48 @@ +package com.yanzhu.auth.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.ip.IpUtils; +import com.yanzhu.system.api.RemoteLogService; +import com.yanzhu.system.api.domain.SysLogininfor; + +/** + * 记录日志方法 + * + * @author ruoyi + */ +@Component +public class SysRecordLogService +{ + @Autowired + private RemoteLogService remoteLogService; + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息内容 + * @return + */ + public void recordLogininfor(String username, String status, String message) + { + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(IpUtils.getIpAddr()); + logininfor.setMsg(message); + // 日志状态 + if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) + { + logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.LOGIN_FAIL_STATUS); + } + remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); + } +} diff --git a/yanzhu-auth/src/main/resources/banner.txt b/yanzhu-auth/src/main/resources/banner.txt new file mode 100644 index 00000000..97c5c27c --- /dev/null +++ b/yanzhu-auth/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ _ + (_) | | | | + _ __ _ _ ___ _ _ _ ______ __ _ _ _ | |_ | |__ +| '__|| | | | / _ \ | | | || ||______| / _` || | | || __|| '_ \ +| | | |_| || (_) || |_| || | | (_| || |_| || |_ | | | | +|_| \__,_| \___/ \__, ||_| \__,_| \__,_| \__||_| |_| + __/ | + |___/ \ No newline at end of file diff --git a/yanzhu-auth/src/main/resources/bootstrap.yml b/yanzhu-auth/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..f9979fbb --- /dev/null +++ b/yanzhu-auth/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9200 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-auth + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-auth/src/main/resources/logback.xml b/yanzhu-auth/src/main/resources/logback.xml new file mode 100644 index 00000000..da8f7bb8 --- /dev/null +++ b/yanzhu-auth/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-common/pom.xml b/yanzhu-common/pom.xml new file mode 100644 index 00000000..86551b8b --- /dev/null +++ b/yanzhu-common/pom.xml @@ -0,0 +1,30 @@ + + + + com.yanzhu + yanzhu + 3.6.2 + + 4.0.0 + + + yanzhu-common-log + yanzhu-common-core + yanzhu-common-redis + yanzhu-common-seata + yanzhu-common-swagger + yanzhu-common-security + yanzhu-common-datascope + yanzhu-common-datasource + yanzhu-common-mapper + + + yanzhu-common + pom + + + yanzhu-common通用模块 + + + diff --git a/yanzhu-common/yanzhu-common-core/pom.xml b/yanzhu-common/yanzhu-common-core/pom.xml new file mode 100644 index 00000000..50c3d819 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/pom.xml @@ -0,0 +1,117 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-core + + + yanzhu-common-core核心模块 + + + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + com.alibaba + transmittable-thread-local + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.alibaba.fastjson2 + fastjson2 + + + + + io.jsonwebtoken + jjwt + + + + + javax.xml.bind + jaxb-api + + + + + org.apache.commons + commons-lang3 + + + + + commons-io + commons-io + + + + + org.apache.poi + poi-ooxml + + + + + javax.servlet + javax.servlet-api + + + + + io.swagger + swagger-annotations + + + + diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excel.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excel.java new file mode 100644 index 00000000..72e31394 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excel.java @@ -0,0 +1,183 @@ +package com.yanzhu.common.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.math.BigDecimal; + +import com.yanzhu.common.core.utils.poi.ExcelHandlerAdapter; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; + +/** + * 自定义导出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 ""; + + /** + * 读取内容转表达式 (如: 0=男,1=女,2=未知) + */ + public String readConverterExp() default ""; + + /** + * 分隔符,读取字符串组内容 + */ + public String separator() default ","; + + /** + * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) + */ + public int scale() default -1; + + /** + * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN + */ + public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; + + /** + * 导出时在excel中每个列的高度 单位为字符 + */ + public double height() default 14; + + /** + * 导出时在excel中每个列的宽 单位为字符 + */ + public double width() default 16; + + /** + * 文字后缀,如% 90 变成90% + */ + public String suffix() default ""; + + /** + * 当值为空时,字段的默认值 + */ + public String defaultValue() default ""; + + /** + * 提示信息 + */ + public String prompt() default ""; + + /** + * 设置只能选择不能输入的列内容. + */ + public String[] combo() default {}; + + /** + * 是否需要纵向合并单元格,应对需求:含有list集合单元格) + */ + public boolean needMerge() default false; + + /** + * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. + */ + public boolean isExport() default true; + + /** + * 另一个类中的属性名称,支持多级获取,以小数点隔开 + */ + public String targetAttr() default ""; + + /** + * 是否自动统计数据,在最后追加一行统计数据总和 + */ + public boolean isStatistics() default false; + + /** + * 导出类型(0数字 1字符串) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出列头背景色 + */ + public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT; + + /** + * 导出列头字体颜色 + */ + public IndexedColors headerColor() default IndexedColors.WHITE; + + /** + * 导出单元格背景色 + */ + public IndexedColors backgroundColor() default IndexedColors.WHITE; + + /** + * 导出单元格字体颜色 + */ + public IndexedColors color() default IndexedColors.BLACK; + + /** + * 导出字段对齐方式 + */ + public HorizontalAlignment align() default HorizontalAlignment.CENTER; + + /** + * 自定义数据处理器 + */ + public Class handler() default ExcelHandlerAdapter.class; + + /** + * 自定义数据处理器参数 + */ + public String[] args() default {}; + + /** + * 字段类型(0:导出导入;1:仅导出;2:仅导入) + */ + Type type() default Type.ALL; + + public enum Type + { + ALL(0), EXPORT(1), IMPORT(2); + private final int value; + + Type(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + public enum ColumnType + { + NUMERIC(0), STRING(1), IMAGE(2); + private final int value; + + ColumnType(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excels.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excels.java new file mode 100644 index 00000000..8e037cbf --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/Excels.java @@ -0,0 +1,18 @@ +package com.yanzhu.common.core.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 +{ + Excel[] value(); +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/RateLimiter.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/RateLimiter.java new file mode 100644 index 00000000..6f38cd48 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/annotation/RateLimiter.java @@ -0,0 +1,37 @@ +package com.yanzhu.common.core.annotation; + +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.enums.LimitType; + +import java.lang.annotation.*; + +/** + * 限流注解 + * + * @author JiangYuQi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RateLimiter +{ + /** + * 限流key + */ + public String key() default CacheConstants.RATE_LIMIT_KEY; + + /** + * 限流时间,单位秒 + */ + public int time() default 60; + + /** + * 限流次数 + */ + public int count() default 100; + + /** + * 限流类型 + */ + public LimitType limitType() default LimitType.DEFAULT; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/CacheConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/CacheConstants.java new file mode 100644 index 00000000..dee18466 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/CacheConstants.java @@ -0,0 +1,75 @@ +package com.yanzhu.common.core.constant; + +/** + * 缓存常量信息 + * + * @author ruoyi + */ +public class CacheConstants +{ + + /** + * 缓存有效期,默认720(分钟) + */ + public final static long EXPIRATION = 720; + + /** + * 缓存刷新时间,默认120(分钟) + */ + public final static long REFRESH_TIME = 120; + + /** + * 密码最大错误次数 + */ + public final static int PASSWORD_MAX_RETRY_COUNT = 5; + + /** + * 密码锁定时间,默认10(分钟) + */ + public final static long PASSWORD_LOCK_TIME = 10; + + /** + * 权限缓存前缀 + */ + public final static String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 地址管理 cache key + */ + public static final String SYS_AREA_ALL = "sys_area:"; + + /** + * 地址管理_城市 cache key + */ + public static final String SYS_AREA_CITY = "sys_area_city:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 登录账户密码错误次数 redis key + */ + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; + + /** + * 登录IP黑名单 cache key + */ + public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList"; + + /** + * 限流 redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/Constants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/Constants.java new file mode 100644 index 00000000..f7716976 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/Constants.java @@ -0,0 +1,130 @@ +package com.yanzhu.common.core.constant; + +/** + * 通用常量信息 + * + * @author ruoyi + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * www主域 + */ + public static final String WWW = "www."; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi:"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap:"; + + /** + * LDAPS 远程方法调用 + */ + public static final String LOOKUP_LDAPS = "ldaps:"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 成功标记 + */ + public static final Integer SUCCESS = 200; + + /** + * 失败标记 + */ + public static final Integer FAIL = 500; + + /** + * 登录成功状态 + */ + public static final String LOGIN_SUCCESS_STATUS = "0"; + + /** + * 登录失败状态 + */ + public static final String LOGIN_FAIL_STATUS = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 当前记录起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * 验证码有效期(分钟) + */ + public static final long CAPTCHA_EXPIRATION = 2; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) + */ + public static final String[] JOB_WHITELIST_STR = { "com.yanzhu" }; + + /** + * 定时任务违规的字符 + */ + public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", + "org.springframework", "org.apache", "com.yanzhu.common.core.utils.file" }; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/GenConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/GenConstants.java new file mode 100644 index 00000000..37739a98 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/GenConstants.java @@ -0,0 +1,117 @@ +package com.yanzhu.common.core.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", + "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" }; + + /** 文本框 */ + public static final String HTML_INPUT = "input"; + + /** 文本域 */ + public static final String HTML_TEXTAREA = "textarea"; + + /** 下拉框 */ + public static final String HTML_SELECT = "select"; + + /** 单选框 */ + public static final String HTML_RADIO = "radio"; + + /** 复选框 */ + public static final String HTML_CHECKBOX = "checkbox"; + + /** 日期控件 */ + public static final String HTML_DATETIME = "datetime"; + + /** 图片上传控件 */ + public static final String HTML_IMAGE_UPLOAD = "imageUpload"; + + /** 文件上传控件 */ + public static final String HTML_FILE_UPLOAD = "fileUpload"; + + /** 富文本控件 */ + public static final String HTML_EDITOR = "editor"; + + /** 字符串类型 */ + public static final String TYPE_STRING = "String"; + + /** 整型 */ + public static final String TYPE_INTEGER = "Integer"; + + /** 长整型 */ + public static final String TYPE_LONG = "Long"; + + /** 浮点型 */ + public static final String TYPE_DOUBLE = "Double"; + + /** 高精度计算类型 */ + public static final String TYPE_BIGDECIMAL = "BigDecimal"; + + /** 时间类型 */ + public static final String TYPE_DATE = "Date"; + + /** 模糊查询 */ + public static final String QUERY_LIKE = "LIKE"; + + /** 相等查询 */ + public static final String QUERY_EQ = "EQ"; + + /** 需要 */ + public static final String REQUIRE = "1"; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/HttpStatus.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/HttpStatus.java new file mode 100644 index 00000000..0d36f00e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/HttpStatus.java @@ -0,0 +1,94 @@ +package com.yanzhu.common.core.constant; + +/** + * 返回状态码 + * + * @author ruoyi + */ +public class HttpStatus +{ + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + public static final int WARN = 601; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ScheduleConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ScheduleConstants.java new file mode 100644 index 00000000..d86752d0 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ScheduleConstants.java @@ -0,0 +1,50 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/SecurityConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/SecurityConstants.java new file mode 100644 index 00000000..7cfbf317 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/SecurityConstants.java @@ -0,0 +1,55 @@ +package com.yanzhu.common.core.constant; + +/** + * 权限相关通用常量 + * + * @author ruoyi + */ +public class SecurityConstants +{ + /** + * 用户ID字段 + */ + public static final String DETAILS_USER_ID = "user_id"; + + /** + * 用户名字段 + */ + public static final String DETAILS_USERNAME = "username"; + + /** + * 授权信息字段 + */ + public static final String AUTHORIZATION_HEADER = "authorization"; + + /** + * 请求来源 + */ + public static final String FROM_SOURCE = "from-source"; + + /** + * 内部请求 + */ + public static final String INNER = "inner"; + + /** + * 用户标识 + */ + public static final String USER_KEY = "user_key"; + + /** + * 登录用户 + */ + public static final String LOGIN_USER = "login_user"; + + + /** + * 微信小程序登录用户 + */ + public static final String LOGIN_USER_WX = "login_user_wx"; + + /** + * 角色权限 + */ + public static final String ROLE_PERMISSION = "role_permission"; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ServiceNameConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ServiceNameConstants.java new file mode 100644 index 00000000..48ec0f53 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/ServiceNameConstants.java @@ -0,0 +1,34 @@ +package com.yanzhu.common.core.constant; + +/** + * 服务名称 + * + * @author ruoyi + */ +public class ServiceNameConstants +{ + /** + * 认证服务的serviceid + */ + public static final String AUTH_SERVICE = "ruoyi-auth"; + + /** + * 系统模块的serviceid + */ + public static final String SYSTEM_SERVICE = "ruoyi-system"; + + /** + * 管理模块的serviceid + */ + public static final String MANAGE_SERVICE = "ruoyi-manage"; + + /** + * 微信模块的serviceid + */ + public static final String WECHAT_SERVICE = "ruoyi-wechat"; + + /** + * 文件服务的serviceid + */ + public static final String FILE_SERVICE = "ruoyi-file"; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/TokenConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/TokenConstants.java new file mode 100644 index 00000000..92d1499e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/TokenConstants.java @@ -0,0 +1,25 @@ +package com.yanzhu.common.core.constant; + +/** + * Token的Key常量 + * + * @author ruoyi + */ +public class TokenConstants +{ + /** + * 令牌自定义标识 + */ + public static final String AUTHENTICATION = "Authorization"; + + /** + * 令牌前缀 + */ + public static final String PREFIX = "Bearer "; + + /** + * 令牌秘钥 + */ + public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; + +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/UserConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/UserConstants.java new file mode 100644 index 00000000..d7cc784f --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/UserConstants.java @@ -0,0 +1,80 @@ +package com.yanzhu.common.core.constant; + +/** + * 用户常量信息 + * + * @author ruoyi + */ +public class UserConstants +{ + /** + * 平台内系统用户的唯一标志 + */ + public static final String SYS_USER = "SYS_USER"; + + /** 正常状态 */ + public static final String NORMAL = "0"; + + /** 异常状态 */ + public static final String EXCEPTION = "1"; + + /** 用户封禁状态 */ + public static final String USER_DISABLE = "1"; + + /** 角色封禁状态 */ + public static final String ROLE_DISABLE = "1"; + + /** 部门正常状态 */ + public static final String DEPT_NORMAL = "0"; + + /** 部门停用状态 */ + public static final String DEPT_DISABLE = "1"; + + /** 字典正常状态 */ + public static final String DICT_NORMAL = "0"; + + /** 是否为系统默认(是) */ + public static final String YES = "Y"; + + /** 是否菜单外链(是) */ + public static final String YES_FRAME = "0"; + + /** 是否菜单外链(否) */ + public static final String NO_FRAME = "1"; + + /** 菜单类型(目录) */ + public static final String TYPE_DIR = "M"; + + /** 菜单类型(菜单) */ + public static final String TYPE_MENU = "C"; + + /** 菜单类型(按钮) */ + public static final String TYPE_BUTTON = "F"; + + /** Layout组件标识 */ + public final static String LAYOUT = "Layout"; + + /** ParentView组件标识 */ + public final static String PARENT_VIEW = "ParentView"; + + /** InnerLink组件标识 */ + public final static String INNER_LINK = "InnerLink"; + + /** 校验是否唯一的返回标识 */ + public final static boolean UNIQUE = true; + public final static boolean NOT_UNIQUE = false; + + /** + * 用户名长度限制 + */ + public static final int USERNAME_MIN_LENGTH = 2; + + public static final int USERNAME_MAX_LENGTH = 20; + + /** + * 密码长度限制 + */ + public static final int PASSWORD_MIN_LENGTH = 5; + + public static final int PASSWORD_MAX_LENGTH = 20; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/WechatConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/WechatConstants.java new file mode 100644 index 00000000..70f6e4a4 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/WechatConstants.java @@ -0,0 +1,14 @@ +package com.yanzhu.common.core.constant; + +/** + * 常量信息 + */ +public class WechatConstants { + /** + * openid + */ + public final static String OPENID = "OpenId"; + + public final static String WXUSERSESSIONKEY = "WxUserSessionKey"; + +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/modules/ManageCacheConstants.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/modules/ManageCacheConstants.java new file mode 100644 index 00000000..4b2476cc --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/constant/modules/ManageCacheConstants.java @@ -0,0 +1,22 @@ +package com.yanzhu.common.core.constant.modules; + +/** + * 业务缓存常量 + */ +public class ManageCacheConstants { + + /** + * 数据缓存有效期,2(分钟) + */ + public final static Long TIME = 2L; + + /** + * 行业标签缓存 + */ + public final static String baseTag_All = "baseTag.findAll:"; + + /** + * 行业类型缓存 + */ + public final static String baseTagIndustry_All = "baseTagIndustry.findAll:"; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/context/SecurityContextHolder.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/context/SecurityContextHolder.java new file mode 100644 index 00000000..eabfa1f1 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/context/SecurityContextHolder.java @@ -0,0 +1,98 @@ +package com.yanzhu.common.core.context; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import com.alibaba.ttl.TransmittableThreadLocal; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 获取当前线程变量中的 用户id、用户名称、Token等信息 + * 注意: 必须在网关通过请求头的方法传入,同时在HeaderInterceptor拦截器设置值。 否则这里无法获取 + * + * @author ruoyi + */ +public class SecurityContextHolder +{ + private static final TransmittableThreadLocal> THREAD_LOCAL = new TransmittableThreadLocal<>(); + + public static void set(String key, Object value) + { + Map map = getLocalMap(); + map.put(key, value == null ? StringUtils.EMPTY : value); + } + + public static String get(String key) + { + Map map = getLocalMap(); + return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY)); + } + + public static T get(String key, Class clazz) + { + Map map = getLocalMap(); + return StringUtils.cast(map.getOrDefault(key, null)); + } + + public static Map getLocalMap() + { + Map map = THREAD_LOCAL.get(); + if (map == null) + { + map = new ConcurrentHashMap(); + THREAD_LOCAL.set(map); + } + return map; + } + + public static void setLocalMap(Map threadLocalMap) + { + THREAD_LOCAL.set(threadLocalMap); + } + + public static Long getUserId() + { + return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L); + } + + public static void setUserId(String account) + { + set(SecurityConstants.DETAILS_USER_ID, account); + } + + public static String getUserName() + { + return get(SecurityConstants.DETAILS_USERNAME); + } + + public static void setUserName(String username) + { + set(SecurityConstants.DETAILS_USERNAME, username); + } + + public static String getUserKey() + { + return get(SecurityConstants.USER_KEY); + } + + public static void setUserKey(String userKey) + { + set(SecurityConstants.USER_KEY, userKey); + } + + public static String getPermission() + { + return get(SecurityConstants.ROLE_PERMISSION); + } + + public static void setPermission(String permissions) + { + set(SecurityConstants.ROLE_PERMISSION, permissions); + } + + public static void remove() + { + THREAD_LOCAL.remove(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/domain/R.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/domain/R.java new file mode 100644 index 00000000..6fa1fe14 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/domain/R.java @@ -0,0 +1,115 @@ +package com.yanzhu.common.core.domain; + +import java.io.Serializable; +import com.yanzhu.common.core.constant.Constants; + +/** + * 响应信息主体 + * + * @author ruoyi + */ +public class R implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 成功 */ + public static final int SUCCESS = Constants.SUCCESS; + + /** 失败 */ + public static final int FAIL = Constants.FAIL; + + private int code; + + private String msg; + + private T data; + + public static R ok() + { + return restResult(null, SUCCESS, null); + } + + public static R ok(T data) + { + return restResult(data, SUCCESS, null); + } + + public static R ok(T data, String msg) + { + return restResult(data, SUCCESS, msg); + } + + public static R fail() + { + return restResult(null, FAIL, null); + } + + public static R fail(String msg) + { + return restResult(null, FAIL, msg); + } + + public static R fail(T data) + { + return restResult(data, FAIL, null); + } + + public static R fail(T data, String msg) + { + return restResult(data, FAIL, msg); + } + + public static R fail(int code, String msg) + { + return restResult(null, code, msg); + } + + private static R restResult(T data, int code, String msg) + { + R apiResult = new R<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public T getData() + { + return data; + } + + public void setData(T data) + { + this.data = data; + } + + public static Boolean isError(R ret) + { + return !isSuccess(ret); + } + + public static Boolean isSuccess(R ret) + { + return R.SUCCESS == ret.getCode(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/IsDelEnums.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/IsDelEnums.java new file mode 100644 index 00000000..ca38dfb8 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/IsDelEnums.java @@ -0,0 +1,31 @@ +package com.yanzhu.common.core.enums; + +/** + * 是否有效 + * + * @author JiangYuQi + */ +public enum IsDelEnums { + + NO(0L, "有效"), + YES(1L, "删除"); + + private final Long code; + private final String info; + + IsDelEnums(Long code, String info) + { + this.code = code; + this.info = info; + } + + public Long getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/LimitType.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/LimitType.java new file mode 100644 index 00000000..4a646b6e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/LimitType.java @@ -0,0 +1,19 @@ +package com.yanzhu.common.core.enums; + +/** + * 限流类型 + * + * @author JiangYuQi + */ +public enum LimitType +{ + /** + * 默认策略全局限流 + */ + DEFAULT, + + /** + * 根据请求者IP进行限流 + */ + IP +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/OwnerType.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/OwnerType.java new file mode 100644 index 00000000..341875ef --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/OwnerType.java @@ -0,0 +1,30 @@ +package com.yanzhu.common.core.enums; + +/** + * 雇主类型 + */ +public enum OwnerType { + + GR(1L, "个人"), + QY(2L, "企业"); + + private final Long code; + private final String info; + + OwnerType (Long code, String info) + { + this.code = code; + this.info = info; + } + + public Long getCode() + { + return code; + } + + public String getInfo() + { + return info; + } + +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/RegisterChannelEnums.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/RegisterChannelEnums.java new file mode 100644 index 00000000..488a74f7 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/RegisterChannelEnums.java @@ -0,0 +1,28 @@ +package com.yanzhu.common.core.enums; +/** + * 注册渠道 + * + * @author ZhouJiXiang + */ +public enum RegisterChannelEnums { + WXMINI(0L, "微信小程序"); + + private final Long code; + private final String info; + + RegisterChannelEnums(Long code, String info) + { + this.code = code; + this.info = info; + } + + public Long getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/SignUpTypeEnums.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/SignUpTypeEnums.java new file mode 100644 index 00000000..f79fbc18 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/SignUpTypeEnums.java @@ -0,0 +1,31 @@ +package com.yanzhu.common.core.enums; + +/** + * 报名入围类型 + * + * @author JiangYuQi + */ +public enum SignUpTypeEnums { + + HX(1L, "雇主海选"), + ZJ(2L, "用户自荐"); + + private final Long code; + private final String info; + + SignUpTypeEnums (Long code, String info) + { + this.code = code; + this.info = info; + } + + public Long getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/TaskStatus.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/TaskStatus.java new file mode 100644 index 00000000..4ba8f5bc --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/TaskStatus.java @@ -0,0 +1,31 @@ +package com.yanzhu.common.core.enums; + +/** + * 任务状态 + */ +public enum TaskStatus { + + check(10L, "审核中"), + finish(99L, "已结束"), + active(100L, "发布中"); + + private final Long code; + private final String info; + + TaskStatus (Long code, String info) + { + this.code = code; + this.info = info; + } + + public Long getCode() + { + return code; + } + + public String getInfo() + { + return info; + } + +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/UserStatus.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/UserStatus.java new file mode 100644 index 00000000..b5034176 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/enums/UserStatus.java @@ -0,0 +1,30 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CaptchaException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CaptchaException.java new file mode 100644 index 00000000..3b37813e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CaptchaException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.exception; + +/** + * 验证码错误异常类 + * + * @author ruoyi + */ +public class CaptchaException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public CaptchaException(String msg) + { + super(msg); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CheckedException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CheckedException.java new file mode 100644 index 00000000..d0900d13 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/CheckedException.java @@ -0,0 +1,31 @@ +package com.yanzhu.common.core.exception; + +/** + * 检查异常 + * + * @author ruoyi + */ +public class CheckedException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public CheckedException(String message) + { + super(message); + } + + public CheckedException(Throwable cause) + { + super(cause); + } + + public CheckedException(String message, Throwable cause) + { + super(message, cause); + } + + public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/DemoModeException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/DemoModeException.java new file mode 100644 index 00000000..87890ea7 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/DemoModeException.java @@ -0,0 +1,15 @@ +package com.yanzhu.common.core.exception; + +/** + * 演示模式异常 + * + * @author ruoyi + */ +public class DemoModeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public DemoModeException() + { + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/GlobalException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/GlobalException.java new file mode 100644 index 00000000..1c85df42 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/GlobalException.java @@ -0,0 +1,58 @@ +package com.yanzhu.common.core.exception; + +/** + * 全局异常 + * + * @author ruoyi + */ +public class GlobalException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public GlobalException() + { + } + + public GlobalException(String message) + { + this.message = message; + } + + public String getDetailMessage() + { + return detailMessage; + } + + public GlobalException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() + { + return message; + } + + public GlobalException setMessage(String message) + { + this.message = message; + return this; + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/InnerAuthException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/InnerAuthException.java new file mode 100644 index 00000000..f1a0e007 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/InnerAuthException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.exception; + +/** + * 内部认证异常 + * + * @author ruoyi + */ +public class InnerAuthException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public InnerAuthException(String message) + { + super(message); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/PreAuthorizeException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/PreAuthorizeException.java new file mode 100644 index 00000000..a1517a59 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/PreAuthorizeException.java @@ -0,0 +1,15 @@ +package com.yanzhu.common.core.exception; + +/** + * 权限异常 + * + * @author ruoyi + */ +public class PreAuthorizeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public PreAuthorizeException() + { + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/ServiceException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/ServiceException.java new file mode 100644 index 00000000..6a6c6d96 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/ServiceException.java @@ -0,0 +1,74 @@ +package com.yanzhu.common.core.exception; + +/** + * 业务异常 + * + * @author ruoyi + */ +public final class ServiceException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + private Integer code; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public ServiceException() + { + } + + public ServiceException(String message) + { + this.message = message; + } + + public ServiceException(String message, Integer code) + { + this.message = message; + this.code = code; + } + + public String getDetailMessage() + { + return detailMessage; + } + + @Override + public String getMessage() + { + return message; + } + + public Integer getCode() + { + return code; + } + + public ServiceException setMessage(String message) + { + this.message = message; + return this; + } + + public ServiceException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/UtilException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/UtilException.java new file mode 100644 index 00000000..086fa84e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/UtilException.java @@ -0,0 +1,26 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotLoginException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotLoginException.java new file mode 100644 index 00000000..bfc7ab29 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotLoginException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.exception.auth; + +/** + * 未能通过的登录认证异常 + * + * @author ruoyi + */ +public class NotLoginException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public NotLoginException(String message) + { + super(message); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotPermissionException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotPermissionException.java new file mode 100644 index 00000000..a76abb57 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotPermissionException.java @@ -0,0 +1,23 @@ +package com.yanzhu.common.core.exception.auth; + +import org.apache.commons.lang3.StringUtils; + +/** + * 未能通过的权限认证异常 + * + * @author ruoyi + */ +public class NotPermissionException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public NotPermissionException(String permission) + { + super(permission); + } + + public NotPermissionException(String[] permissions) + { + super(StringUtils.join(permissions, ",")); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotRoleException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotRoleException.java new file mode 100644 index 00000000..eec529d6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/auth/NotRoleException.java @@ -0,0 +1,23 @@ +package com.yanzhu.common.core.exception.auth; + +import org.apache.commons.lang3.StringUtils; + +/** + * 未能通过的角色认证异常 + * + * @author ruoyi + */ +public class NotRoleException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public NotRoleException(String role) + { + super(role); + } + + public NotRoleException(String[] roles) + { + super(StringUtils.join(roles, ",")); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/base/BaseException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/base/BaseException.java new file mode 100644 index 00000000..37c9da2a --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/base/BaseException.java @@ -0,0 +1,79 @@ +package com.yanzhu.common.core.exception.base; + +/** + * 基础异常 + * + * @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); + } + + public String getModule() + { + return module; + } + + public String getCode() + { + return code; + } + + public Object[] getArgs() + { + return args; + } + + public String getDefaultMessage() + { + return defaultMessage; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileException.java new file mode 100644 index 00000000..2b9fcfee --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileException.java @@ -0,0 +1,19 @@ +package com.yanzhu.common.core.exception.file; + +import com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileNameLengthLimitExceededException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileNameLengthLimitExceededException.java new file mode 100644 index 00000000..43559401 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileNameLengthLimitExceededException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileSizeLimitExceededException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileSizeLimitExceededException.java new file mode 100644 index 00000000..1d04779b --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileSizeLimitExceededException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileUploadException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileUploadException.java new file mode 100644 index 00000000..977b1a00 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/FileUploadException.java @@ -0,0 +1,61 @@ +package com.yanzhu.common.core.exception.file; + +import java.io.PrintStream; +import java.io.PrintWriter; + +/** + * 文件上传异常类 + * + * @author ruoyi + */ +public class FileUploadException extends Exception +{ + + private static final long serialVersionUID = 1L; + + private final Throwable cause; + + public FileUploadException() + { + this(null, null); + } + + public FileUploadException(final String msg) + { + this(msg, null); + } + + public FileUploadException(String msg, Throwable cause) + { + super(msg); + this.cause = cause; + } + + @Override + public void printStackTrace(PrintStream stream) + { + super.printStackTrace(stream); + if (cause != null) + { + stream.println("Caused by:"); + cause.printStackTrace(stream); + } + } + + @Override + public void printStackTrace(PrintWriter writer) + { + super.printStackTrace(writer); + if (cause != null) + { + writer.println("Caused by:"); + cause.printStackTrace(writer); + } + } + + @Override + public Throwable getCause() + { + return cause; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/InvalidExtensionException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/InvalidExtensionException.java new file mode 100644 index 00000000..d7fb9942 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/file/InvalidExtensionException.java @@ -0,0 +1,80 @@ +package com.yanzhu.common.core.exception.file; + +import java.util.Arrays; + +/** + * 文件上传 误异常类 + * + * @author ruoyi + */ +public class InvalidExtensionException extends FileUploadException +{ + private static final long serialVersionUID = 1L; + + private String[] allowedExtension; + private String extension; + private String filename; + + public InvalidExtensionException(String[] allowedExtension, String extension, String filename) + { + super("filename : [" + 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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/job/TaskException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/job/TaskException.java new file mode 100644 index 00000000..ebb0dce1 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/job/TaskException.java @@ -0,0 +1,34 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/CaptchaExpireException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/CaptchaExpireException.java new file mode 100644 index 00000000..f0efc1ea --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/CaptchaExpireException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserException.java new file mode 100644 index 00000000..7e239612 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserException.java @@ -0,0 +1,18 @@ +package com.yanzhu.common.core.exception.user; + +import com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserPasswordNotMatchException.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserPasswordNotMatchException.java new file mode 100644 index 00000000..8fc565c2 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/exception/user/UserPasswordNotMatchException.java @@ -0,0 +1,16 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/CharsetKit.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/CharsetKit.java new file mode 100644 index 00000000..0fbfaed0 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/CharsetKit.java @@ -0,0 +1,86 @@ +package com.yanzhu.common.core.text; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/Convert.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/Convert.java new file mode 100644 index 00000000..2fc87744 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/Convert.java @@ -0,0 +1,1006 @@ +package com.yanzhu.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.yanzhu.common.core.utils.StringUtils; + +/** + * 类型转换器 + * + * @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 str 被转换的值 + * @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 str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[] || obj instanceof Byte[]) + { + if (obj instanceof byte[]) + { + return str((byte[]) obj, charset); + } + else + { + Byte[] bytes = (Byte[]) obj; + int length = bytes.length; + byte[] dest = new byte[length]; + for (int i = 0; i < length; i++) + { + dest[i] = bytes[i]; + } + return str(dest, 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); + } + } + return new String(c); + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/StrFormatter.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/StrFormatter.java new file mode 100644 index 00000000..8086aa9f --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/text/StrFormatter.java @@ -0,0 +1,92 @@ +package com.yanzhu.common.core.text; + +import com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/DateUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/DateUtils.java new file mode 100644 index 00000000..265293c6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/DateUtils.java @@ -0,0 +1,183 @@ +package com.yanzhu.common.core.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间工具类 + * + * @author ruoyi + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils +{ + public static String YYYY = "yyyy"; + + public static String YYYY_MM = "yyyy-MM"; + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获取当前Date型日期 + * + * @return Date() 当前日期 + */ + public static Date getNowDate() + { + return new Date(); + } + + /** + * 获取当前日期, 默认格式为yyyy-MM-dd + * + * @return String + */ + public static String getDate() + { + return dateTimeNow(YYYY_MM_DD); + } + + public static final String getTime() + { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static final String dateTimeNow() + { + return dateTimeNow(YYYYMMDDHHMMSS); + } + + public static final String dateTimeNow(final String format) + { + return parseDateToStr(format, new Date()); + } + + public static final String dateTime(final Date date) + { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static final String parseDateToStr(final String format, final Date date) + { + return new SimpleDateFormat(format).format(date); + } + + public static final Date dateTime(final String format, final String ts) + { + try + { + return new SimpleDateFormat(format).parse(ts); + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 即年/月/日 如2018/08/08 + */ + public static final String datePath() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 即年/月/日 如20180808 + */ + public static final String dateTime() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 格式 + */ + public static Date parseDate(Object str) + { + if (str == null) + { + return null; + } + try + { + return parseDate(str.toString(), parsePatterns); + } + catch (ParseException e) + { + return null; + } + } + + /** + * 获取服务器启动时间 + */ + public static Date getServerStartDate() + { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算时间差 + * + * @param endTime 最后时间 + * @param startTime 开始时间 + * @return 时间差(天/小时/分钟) + */ + public static String timeDistance(Date endDate, Date startTime) + { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - startTime.getTime(); + // 计算差多少天 + long day = diff / nd; + // 计算差多少小时 + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "小时" + min + "分钟"; + } + + /** + * 增加 LocalDateTime ==> Date + */ + public static Date toDate(LocalDateTime temporalAccessor) + { + ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } + + /** + * 增加 LocalDate ==> Date + */ + public static Date toDate(LocalDate temporalAccessor) + { + LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); + ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ExceptionUtil.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ExceptionUtil.java new file mode 100644 index 00000000..a898f955 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ExceptionUtil.java @@ -0,0 +1,39 @@ +package com.yanzhu.common.core.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.commons.lang3.exception.ExceptionUtils; + +/** + * 错误信息处理类。 + * + * @author ruoyi + */ +public class ExceptionUtil +{ + /** + * 获取exception的详细错误信息。 + */ + public static String getExceptionMessage(Throwable e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + return sw.toString(); + } + + public static String getRootErrorMessage(Exception e) + { + Throwable root = ExceptionUtils.getRootCause(e); + root = (root == null ? e : root); + if (root == null) + { + return ""; + } + String msg = root.getMessage(); + if (msg == null) + { + return "null"; + } + return StringUtils.defaultString(msg); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/JwtUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/JwtUtils.java new file mode 100644 index 00000000..b90429b9 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/JwtUtils.java @@ -0,0 +1,123 @@ +package com.yanzhu.common.core.utils; + +import java.util.Map; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.TokenConstants; +import com.yanzhu.common.core.text.Convert; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * Jwt工具类 + * + * @author ruoyi + */ +public class JwtUtils +{ + public static String secret = TokenConstants.SECRET; + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + public static String createToken(Map claims) + { + String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + public static Claims parseToken(String token) + { + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + + /** + * 根据令牌获取用户标识 + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserKey(String token) + { + Claims claims = parseToken(token); + return getValue(claims, SecurityConstants.USER_KEY); + } + + /** + * 根据令牌获取用户标识 + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserKey(Claims claims) + { + return getValue(claims, SecurityConstants.USER_KEY); + } + + /** + * 根据令牌获取用户ID + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserId(String token) + { + Claims claims = parseToken(token); + return getValue(claims, SecurityConstants.DETAILS_USER_ID); + } + + /** + * 根据身份信息获取用户ID + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserId(Claims claims) + { + return getValue(claims, SecurityConstants.DETAILS_USER_ID); + } + + /** + * 根据令牌获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public static String getUserName(String token) + { + Claims claims = parseToken(token); + return getValue(claims, SecurityConstants.DETAILS_USERNAME); + } + + /** + * 根据身份信息获取用户名 + * + * @param claims 身份信息 + * @return 用户名 + */ + public static String getUserName(Claims claims) + { + return getValue(claims, SecurityConstants.DETAILS_USERNAME); + } + + /** + * 根据身份信息获取键值 + * + * @param claims 身份信息 + * @param key 键 + * @return 值 + */ + public static String getValue(Claims claims, String key) + { + return Convert.toStr(claims.get(key), ""); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/NoUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/NoUtils.java new file mode 100644 index 00000000..0ef19a95 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/NoUtils.java @@ -0,0 +1,37 @@ +package com.yanzhu.common.core.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 编号工具类 + * + * @author JiangYuQi + * @date 2023-11-07 + */ +public class NoUtils { + + private static int Seq = 0; + private static final String PREFIX = "S"; + + /** + * 生成任务编号 + * @author JiangYuQi + * @date 2023-11-07 + */ + public static String nextNo(){ + Date currentTime = new Date(); + SimpleDateFormat formatter = new SimpleDateFormat("YY"); + String dateString = formatter.format(currentTime); + String prefix = String.format("%03d", getNextSequence()); + return PREFIX+dateString+System.currentTimeMillis()+prefix; + } + + private static synchronized int getNextSequence() { + if (Seq >= 99) { + Seq = 0; + } + return ++Seq; + } + +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/PageUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/PageUtils.java new file mode 100644 index 00000000..32a63cd5 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/PageUtils.java @@ -0,0 +1,35 @@ +package com.yanzhu.common.core.utils; + +import com.github.pagehelper.PageHelper; +import com.yanzhu.common.core.utils.sql.SqlUtil; +import com.yanzhu.common.core.web.page.PageDomain; +import com.yanzhu.common.core.web.page.TableSupport; + +/** + * 分页工具类 + * + * @author ruoyi + */ +public class PageUtils extends PageHelper +{ + /** + * 设置请求分页数据 + */ + public static void startPage() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + Boolean reasonable = pageDomain.getReasonable(); + PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); + } + + /** + * 清理分页的线程变量 + */ + public static void clearPage() + { + PageHelper.clearPage(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ServletUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ServletUtils.java new file mode 100644 index 00000000..9357e3ec --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ServletUtils.java @@ -0,0 +1,333 @@ +package com.yanzhu.common.core.utils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.LinkedCaseInsensitiveMap; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import com.alibaba.fastjson2.JSON; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.text.Convert; +import reactor.core.publisher.Mono; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +public class ServletUtils +{ + /** + * 获取String参数 + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name) + { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) + { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParams(ServletRequest request) + { + final Map map = request.getParameterMap(); + return Collections.unmodifiableMap(map); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParamMap(ServletRequest request) + { + Map params = new HashMap<>(); + for (Map.Entry entry : getParams(request).entrySet()) + { + params.put(entry.getKey(), StringUtils.join(entry.getValue(), ",")); + } + return params; + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() + { + try + { + return getRequestAttributes().getRequest(); + } + catch (Exception e) + { + return null; + } + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() + { + try + { + return getRequestAttributes().getResponse(); + } + catch (Exception e) + { + return null; + } + } + + /** + * 获取session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + try + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + catch (Exception e) + { + return null; + } + } + + public static String getHeader(HttpServletRequest request, String name) + { + String value = request.getHeader(name); + if (StringUtils.isEmpty(value)) + { + return StringUtils.EMPTY; + } + return urlDecode(value); + } + + public static Map getHeaders(HttpServletRequest request) + { + Map map = new LinkedCaseInsensitiveMap<>(); + Enumeration enumeration = request.getHeaderNames(); + if (enumeration != null) + { + while (enumeration.hasMoreElements()) + { + String key = enumeration.nextElement(); + String value = request.getHeader(key); + map.put(key, value); + } + } + return map; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) + { + try + { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + String accept = request.getHeader("accept"); + if (accept != null && accept.contains("application/json")) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + return StringUtils.inStringIgnoreCase(ajax, "json", "xml"); + } + + /** + * 内容编码 + * + * @param str 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) + { + try + { + return URLEncoder.encode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) + { + try + { + return URLDecoder.decode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } + + /** + * 设置webflux模型响应 + * + * @param response ServerHttpResponse + * @param value 响应内容 + * @return Mono + */ + public static Mono webFluxResponseWriter(ServerHttpResponse response, Object value) + { + return webFluxResponseWriter(response, HttpStatus.OK, value, R.FAIL); + } + + /** + * 设置webflux模型响应 + * + * @param response ServerHttpResponse + * @param code 响应状态码 + * @param value 响应内容 + * @return Mono + */ + public static Mono webFluxResponseWriter(ServerHttpResponse response, Object value, int code) + { + return webFluxResponseWriter(response, HttpStatus.OK, value, code); + } + + /** + * 设置webflux模型响应 + * + * @param response ServerHttpResponse + * @param status http状态码 + * @param code 响应状态码 + * @param value 响应内容 + * @return Mono + */ + public static Mono webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code) + { + return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code); + } + + /** + * 设置webflux模型响应 + * + * @param response ServerHttpResponse + * @param contentType content-type + * @param status http状态码 + * @param code 响应状态码 + * @param value 响应内容 + * @return Mono + */ + public static Mono webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code) + { + response.setStatusCode(status); + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType); + R result = R.fail(code, value.toString()); + DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(result).getBytes()); + return response.writeWith(Mono.just(dataBuffer)); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/SpringUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/SpringUtils.java new file mode 100644 index 00000000..d37035fc --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/SpringUtils.java @@ -0,0 +1,114 @@ +package com.yanzhu.common.core.utils; + +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.stereotype.Component; + +/** + * spring工具类 方便在非spring管理环境中获取bean + * + * @author ruoyi + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + /** + * 获取对象 + * + * @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(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/StringUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/StringUtils.java new file mode 100644 index 00000000..333c1839 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/StringUtils.java @@ -0,0 +1,561 @@ +package com.yanzhu.common.core.utils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.springframework.util.AntPathMatcher; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.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); + } + + /** + * 判断是否为空,并且不是空白字符 + * + * @param str 要判断的value + * @return 结果 + */ + public static boolean hasText(String str) + { + return (str != null && !str.isEmpty() && containsText(str)); + } + + private static boolean containsText(CharSequence str) + { + int strLen = str.length(); + for (int i = 0; i < strLen; i++) + { + if (!Character.isWhitespace(str.charAt(i))) + { + return true; + } + } + return false; + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用: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列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * + * @param set 给定的集合 + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 + * 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static final String padl(final Number num, final int size) + { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补齐的字符 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 + */ + public static final String padl(final String s, final int size, final char c) + { + final StringBuilder sb = new StringBuilder(size); + if (s != null) + { + final int len = s.length(); + if (s.length() <= size) + { + for (int i = size - len; i > 0; i--) + { + sb.append(c); + } + sb.append(s); + } + else + { + return s.substring(len - size, len); + } + } + else + { + for (int i = size; i > 0; i--) + { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanUtils.java new file mode 100644 index 00000000..59b52779 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanUtils.java @@ -0,0 +1,110 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanValidators.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanValidators.java new file mode 100644 index 00000000..76512f14 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/bean/BeanValidators.java @@ -0,0 +1,24 @@ +package com.yanzhu.common.core.utils.bean; + +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +/** + * bean对象属性验证 + * + * @author ruoyi + */ +public class BeanValidators +{ + public static void validateWithException(Validator validator, Object object, Class... groups) + throws ConstraintViolationException + { + Set> constraintViolations = validator.validate(object, groups); + if (!constraintViolations.isEmpty()) + { + throw new ConstraintViolationException(constraintViolations); + } + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileTypeUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileTypeUtils.java new file mode 100644 index 00000000..24fc519a --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileTypeUtils.java @@ -0,0 +1,95 @@ +package com.yanzhu.common.core.utils.file; + +import java.io.File; +import java.util.Objects; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +/** + * 文件类型工具类 + * + * @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 file 表单文件 + * @return 后缀名 + */ + public static final String getExtension(MultipartFile file) + { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) + { + extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); + } + return extension; + } + + /** + * 获取文件类型 + * + * @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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileUtils.java new file mode 100644 index 00000000..ef00c7db --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/FileUtils.java @@ -0,0 +1,261 @@ +package com.yanzhu.common.core.utils.file; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +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 com.yanzhu.common.core.utils.StringUtils; +import org.apache.commons.lang3.ArrayUtils; + +/** + * 文件处理工具类 + * + * @author ruoyi + */ +public class FileUtils +{ + /** 字符常量:斜杠 {@code '/'} */ + public static final char SLASH = '/'; + + /** 字符常量:反斜杠 {@code '\\'} */ + public static final char BACKSLASH = '\\'; + + 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 + { + if (os != null) + { + try + { + os.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (fis != null) + { + try + { + fis.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 删除文件 + * + * @param filePath 文件 + * @return + */ + public static boolean deleteFile(String filePath) + { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) + { + flag = file.delete(); + } + return flag; + } + + /** + * 文件名称验证 + * + * @param filename 文件名称 + * @return true 正常 false 非法 + */ + public static boolean isValidFilename(String filename) + { + return filename.matches(FILENAME_PATTERN); + } + + /** + * 检查文件是否可下载 + * + * @param resource 需要下载的文件 + * @return true 正常 false 非法 + */ + public static boolean checkAllowDownload(String resource) + { + // 禁止目录上跳级别 + if (StringUtils.contains(resource, "..")) + { + return false; + } + + // 检查允许下载的文件规则 + if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) + { + return true; + } + + // 不在允许下载的文件规则 + return false; + } + + /** + * 下载文件名重新编码 + * + * @param request 请求对象 + * @param fileName 文件名 + * @return 编码后的文件名 + */ + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException + { + final String agent = request.getHeader("USER-AGENT"); + String filename = fileName; + if (agent.contains("MSIE")) + { + // IE浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + filename = filename.replace("+", " "); + } + else if (agent.contains("Firefox")) + { + // 火狐浏览器 + filename = new String(fileName.getBytes(), "ISO8859-1"); + } + else if (agent.contains("Chrome")) + { + // google浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + else + { + // 其它浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + return filename; + } + + /** + * 返回文件名 + * + * @param filePath 文件 + * @return 文件名 + */ + public static String getName(String filePath) + { + if (null == filePath) + { + return null; + } + int len = filePath.length(); + if (0 == len) + { + return filePath; + } + if (isFileSeparator(filePath.charAt(len - 1))) + { + // 以分隔符结尾的去掉结尾分隔符 + len--; + } + + int begin = 0; + char c; + for (int i = len - 1; i > -1; i--) + { + c = filePath.charAt(i); + if (isFileSeparator(c)) + { + // 查找最后一个路径分隔符(/或者\) + begin = i + 1; + break; + } + } + + return filePath.substring(begin, len); + } + + /** + * 是否为Windows或者Linux(Unix)文件分隔符
+ * Windows平台下分隔符为\,Linux(Unix)为/ + * + * @param c 字符 + * @return 是否为Windows或者Linux(Unix)文件分隔符 + */ + public static boolean isFileSeparator(char c) + { + return SLASH == c || BACKSLASH == c; + } + + /** + * 下载文件名重新编码 + * + * @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()); + response.setHeader("download-filename", percentEncodedFileName); + } + + /** + * 百分号编码工具方法 + * + * @param s 需要百分号编码的字符串 + * @return 百分号编码后的字符串 + */ + public static String percentEncode(String s) throws UnsupportedEncodingException + { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); + return encode.replaceAll("\\+", "%20"); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/ImageUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/ImageUtils.java new file mode 100644 index 00000000..d428e1c6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/ImageUtils.java @@ -0,0 +1,84 @@ +package com.yanzhu.common.core.utils.file; + +import java.io.ByteArrayInputStream; +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; + +/** + * 图片处理工具类 + * + * @author ruoyi + */ +public class ImageUtils +{ + private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); + + public static byte[] getImage(String imagePath) + { + InputStream is = getFile(imagePath); + try + { + return IOUtils.toByteArray(is); + } + catch (Exception e) + { + log.error("图片加载异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(is); + } + } + + public static InputStream getFile(String imagePath) + { + try + { + byte[] result = readFile(imagePath); + result = Arrays.copyOf(result, result.length); + return new ByteArrayInputStream(result); + } + catch (Exception e) + { + log.error("获取图片异常 {}", e); + } + return null; + } + + /** + * 读取文件为字节数据 + * + * @param url 地址 + * @return 字节数据 + */ + public static byte[] readFile(String url) + { + InputStream in = null; + try + { + // 网络地址 + URL urlObj = new URL(url); + URLConnection urlConnection = urlObj.openConnection(); + urlConnection.setConnectTimeout(30 * 1000); + urlConnection.setReadTimeout(60 * 1000); + urlConnection.setDoInput(true); + in = urlConnection.getInputStream(); + return IOUtils.toByteArray(in); + } + catch (Exception e) + { + log.error("访问文件异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(in); + } + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/MimeTypeUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/MimeTypeUtils.java new file mode 100644 index 00000000..ac9b8bb5 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/file/MimeTypeUtils.java @@ -0,0 +1,59 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/EscapeUtil.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/EscapeUtil.java new file mode 100644 index 00000000..e6861573 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/EscapeUtil.java @@ -0,0 +1,167 @@ +package com.yanzhu.common.core.utils.html; + +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 转义和反转义工具类 + * + * @author ruoyi + */ +public class EscapeUtil +{ + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + + private static final char[][] TEXT = new char[64][]; + + static + { + for (int i = 0; i < 64; i++) + { + TEXT[i] = new char[] { (char) i }; + } + + // special HTML characters + TEXT['\''] = "'".toCharArray(); // 单引号 + TEXT['"'] = """.toCharArray(); // 双引号 + TEXT['&'] = "&".toCharArray(); // &符 + TEXT['<'] = "<".toCharArray(); // 小于号 + TEXT['>'] = ">".toCharArray(); // 大于号 + } + + /** + * 转义文本中的HTML字符为安全的字符 + * + * @param text 被转义的文本 + * @return 转义后的文本 + */ + public static String escape(String text) + { + return encode(text); + } + + /** + * 还原被转义的HTML特殊字符 + * + * @param content 包含转义符的HTML内容 + * @return 转换后的字符串 + */ + public static String unescape(String content) + { + return decode(content); + } + + /** + * 清除所有HTML标签,但是不删除标签内的内容 + * + * @param content 文本 + * @return 清除标签后的文本 + */ + public static String clean(String content) + { + return new HTMLFilter().filter(content); + } + + /** + * Escape编码 + * + * @param text 被编码的文本 + * @return 编码后的字符 + */ + private static String encode(String text) + { + if (StringUtils.isEmpty(text)) + { + return StringUtils.EMPTY; + } + + final StringBuilder tmp = new StringBuilder(text.length() * 6); + char c; + for (int i = 0; i < text.length(); i++) + { + c = text.charAt(i); + if (c < 256) + { + tmp.append("%"); + if (c < 16) + { + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + else + { + tmp.append("%u"); + if (c <= 0xfff) + { + // issue#I49JU8@Gitee + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + } + return tmp.toString(); + } + + /** + * Escape解码 + * + * @param content 被转义的内容 + * @return 解码后的字符串 + */ + public static String decode(String content) + { + if (StringUtils.isEmpty(content)) + { + return content; + } + + StringBuilder tmp = new StringBuilder(content.length()); + int lastPos = 0, pos = 0; + char ch; + while (lastPos < content.length()) + { + pos = content.indexOf("%", lastPos); + if (pos == lastPos) + { + if (content.charAt(pos + 1) == 'u') + { + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); + tmp.append(ch); + lastPos = pos + 6; + } + else + { + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); + tmp.append(ch); + lastPos = pos + 3; + } + } + else + { + if (pos == -1) + { + tmp.append(content.substring(lastPos)); + lastPos = content.length(); + } + else + { + tmp.append(content.substring(lastPos, pos)); + lastPos = pos; + } + } + } + return tmp.toString(); + } + + public static void main(String[] args) + { + String html = ""; + String escape = EscapeUtil.escape(html); + // String html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println("clean: " + EscapeUtil.clean(html)); + System.out.println("escape: " + escape); + System.out.println("unescape: " + EscapeUtil.unescape(escape)); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/HTMLFilter.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/HTMLFilter.java new file mode 100644 index 00000000..50938e47 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/html/HTMLFilter.java @@ -0,0 +1,570 @@ +package com.yanzhu.common.core.utils.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSS漏洞隐患。 + * + * @author ruoyi + */ +public final class HTMLFilter +{ + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" + * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() + { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[] { "img" }; + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; + vDisallowed = new String[] {}; + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. + vProtocolAtts = new String[] { "src", "href" }; + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) + { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() + { + vTagCounts.clear(); + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) + { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) + { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + // --------------------------------------------------------------- + + /** + * given a user submitted input String, filter out any invalid or restricted html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) + { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + // s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() + { + return alwaysMakeTags; + } + + public boolean isStripComments() + { + return stripComment; + } + + private String escapeComments(final String s) + { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) + { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) + { + if (alwaysMakeTags) + { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + // 不追加结束标签 + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } + else + { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) + { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) + { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) + { + for (int ii = 0; ii < vTagCounts.get(key); ii++) + { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) + { + String result = s; + for (String tag : vRemoveBlanks) + { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) + { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) + { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) + { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) + { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) + { + if (!inArray(name, vSelfClosingTags)) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) + { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) + { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) + { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) + { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) + { + if (inArray(paramName, vProtocolAtts)) + { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\""); + } + } + + if (inArray(name, vSelfClosingTags)) + { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) + { + ending = ""; + } + + if (ending == null || ending.length() < 1) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } + else + { + vTagCounts.put(name, 1); + } + } + else + { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } + else + { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) + { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) + { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) + { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) + { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) + { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) + { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) + { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) + { + if (encodeQuotes) + { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } + else + { + return s; + } + } + + private String checkEntity(final String preamble, final String term) + { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) + { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) + { + for (String item : array) + { + if (item != null && item.equals(s)) + { + return true; + } + } + return false; + } + + private boolean allowed(final String name) + { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) + { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpHelper.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpHelper.java new file mode 100644 index 00000000..6392258a --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpHelper.java @@ -0,0 +1,56 @@ +package com.yanzhu.common.core.utils.http; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * 通用http工具封装 + * + * @author JiangYuQi + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpUtils.java new file mode 100644 index 00000000..d53938fa --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/http/HttpUtils.java @@ -0,0 +1,330 @@ +package com.yanzhu.common.core.utils.http; + +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.*; +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; + +/** + * 通用http发送方法 + * + * @author JiangYuQi + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url) + { + return sendGet(url, StringUtils.EMPTY); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + /** 生产&预生产添加请求代理 **/ + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } + + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param token 请求参数 + * @return 所代表远程资源的响应结果 + */ + public static String doGet(String url, String token ) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + URL realUrl = new URL(url); + 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.setRequestProperty("Access-Token",token); + connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url , e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url , e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url , ex); + } + } + return result.toString(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ip/IpUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ip/IpUtils.java new file mode 100644 index 00000000..c591da32 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/ip/IpUtils.java @@ -0,0 +1,382 @@ +package com.yanzhu.common.core.utils.ip; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils +{ + public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; + // 匹配 ip + public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")"; + public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))"; + // 匹配网段 + public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")"; + + /** + * 获取客户端IP + * + * @return IP地址 + */ + public static String getIpAddr() + { + return getIpAddr(ServletUtils.getRequest()); + } + + /** + * 获取客户端IP + * + * @param request 请求对象 + * @return IP地址 + */ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param ip IP地址 + * @return 结果 + */ + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param addr byte地址 + * @return 结果 + */ + private static boolean internalIp(byte[] addr) + { + if (StringUtils.isNull(addr) || addr.length < 2) + { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) + { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) + { + return true; + } + case SECTION_5: + switch (b1) + { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) + { + if (text.length() == 0) + { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try + { + long l; + int i; + switch (elements.length) + { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) + { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) + { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) + { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } + catch (NumberFormatException e) + { + return null; + } + return bytes; + } + + /** + * 获取IP地址 + * + * @return 本地IP地址 + */ + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + } + return "127.0.0.1"; + } + + /** + * 获取主机名 + * + * @return 本地主机名 + */ + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + } + return "未知"; + } + + /** + * 从多级反向代理中获得第一个非unknown IP地址 + * + * @param ip 获得的IP地址 + * @return 第一个非unknown IP地址 + */ + public static String getMultistageReverseProxyIp(String ip) + { + // 多级反向代理检测 + if (ip != null && ip.indexOf(",") > 0) + { + final String[] ips = ip.trim().split(","); + for (String subIp : ips) + { + if (false == isUnknown(subIp)) + { + ip = subIp; + break; + } + } + } + return StringUtils.substring(ip, 0, 255); + } + + /** + * 检测给定字符串是否为未知,多用于检测HTTP请求相关 + * + * @param checkString 被检测的字符串 + * @return 是否未知 + */ + public static boolean isUnknown(String checkString) + { + return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); + } + + /** + * 是否为IP + */ + public static boolean isIP(String ip) + { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP); + } + + /** + * 是否为IP,或 *为间隔的通配符地址 + */ + public static boolean isIpWildCard(String ip) + { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD); + } + + /** + * 检测参数是否在ip通配符里 + */ + public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) + { + String[] s1 = ipWildCard.split("\\."); + String[] s2 = ip.split("\\."); + boolean isMatchedSeg = true; + for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) + { + if (!s1[i].equals(s2[i])) + { + isMatchedSeg = false; + break; + } + } + return isMatchedSeg; + } + + /** + * 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串 + */ + public static boolean isIPSegment(String ipSeg) + { + return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG); + } + + /** + * 判断ip是否在指定网段中 + */ + public static boolean ipIsInNetNoCheck(String iparea, String ip) + { + int idx = iparea.indexOf('-'); + String[] sips = iparea.substring(0, idx).split("\\."); + String[] sipe = iparea.substring(idx + 1).split("\\."); + String[] sipt = ip.split("\\."); + long ips = 0L, ipe = 0L, ipt = 0L; + for (int i = 0; i < 4; ++i) + { + ips = ips << 8 | Integer.parseInt(sips[i]); + ipe = ipe << 8 | Integer.parseInt(sipe[i]); + ipt = ipt << 8 | Integer.parseInt(sipt[i]); + } + if (ips > ipe) + { + long t = ips; + ips = ipe; + ipe = t; + } + return ips <= ipt && ipt <= ipe; + } + + /** + * 校验ip是否符合过滤串规则 + * + * @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99` + * @param ip 校验IP地址 + * @return boolean 结果 + */ + public static boolean isMatchedIp(String filter, String ip) + { + if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip)) + { + return false; + } + String[] ips = filter.split(";"); + for (String iStr : ips) + { + if (isIP(iStr) && iStr.equals(ip)) + { + return true; + } + else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)) + { + return true; + } + else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)) + { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelHandlerAdapter.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelHandlerAdapter.java new file mode 100644 index 00000000..64075082 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelHandlerAdapter.java @@ -0,0 +1,19 @@ +package com.yanzhu.common.core.utils.poi; + +/** + * Excel数据格式处理适配器 + * + * @author ruoyi + */ +public interface ExcelHandlerAdapter +{ + /** + * 格式化 + * + * @param value 单元格数据值 + * @param args excel注解args参数组 + * + * @return 处理后的值 + */ + Object format(Object value, String[] args); +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelUtil.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelUtil.java new file mode 100644 index 00000000..c287c3b5 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/poi/ExcelUtil.java @@ -0,0 +1,1486 @@ +package com.yanzhu.common.core.utils.poi; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.annotation.Excel.Type; +import com.yanzhu.common.core.annotation.Excels; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.DateUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.file.FileTypeUtils; +import com.yanzhu.common.core.utils.file.ImageUtils; +import com.yanzhu.common.core.utils.reflect.ReflectUtils; + +/** + * Excel相关处理 + * + * @author ruoyi + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; + + public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 当前行号 + */ + private int rownum; + + /** + * 标题 + */ + private String title; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 合并后最后行数 + */ + private int subMergedLastRowNum = 0; + + /** + * 合并后开始行数 + */ + private int subMergedFirstRowNum = 1; + + /** + * 对象的子列表方法 + */ + private Method subMethod; + + /** + * 对象的子列表属性 + */ + private List subFields; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + /** + * 需要排除列属性 + */ + public String[] excludeFields; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + /** + * 隐藏Excel中列属性 + * + * @param fields 列属性名 示例[单个"name"/多个"id","name"] + * @throws Exception + */ + public void hideColumn(String... fields) + { + this.excludeFields = fields; + } + + public void init(List list, String sheetName, String title, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + this.title = title; + createExcelField(); + createWorkbook(); + createTitle(); + createSubHead(); + } + + /** + * 创建excel第一行标题 + */ + public void createTitle() + { + if (StringUtils.isNotEmpty(title)) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + int titleLastCol = this.fields.size() - 1; + if (isSubList()) + { + titleLastCol = titleLastCol + subFields.size() - 1; + } + Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); + titleRow.setHeightInPoints(30); + Cell titleCell = titleRow.createCell(0); + titleCell.setCellStyle(styles.get("title")); + titleCell.setCellValue(title); + sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); + } + } + + /** + * 创建对象的子列表名称 + */ + public void createSubHead() + { + if (isSubList()) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + Row subRow = sheet.createRow(rownum); + int excelNum = 0; + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Cell headCell1 = subRow.createCell(excelNum); + headCell1.setCellValue(attr.name()); + headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + excelNum++; + } + int headFirstRow = excelNum - 1; + int headLastRow = headFirstRow + subFields.size() - 1; + if (headLastRow > headFirstRow) + { + sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); + } + rownum++; + } + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(is, 0); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @param titleNum 标题占用行数 + * @return 转换后集合 + */ + public List importExcel(InputStream is, int titleNum) throws Exception + { + return importExcel(StringUtils.EMPTY, is, titleNum); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + + // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(titleNum); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + List fields = this.getFields(); + Map fieldsMap = new HashMap(); + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, objects); + } + } + for (int i = titleNum + 1; i <= rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + // 判断当前行是否是空行 + if (isRowEmpty(row)) + { + continue; + } + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = (Field) entry.getValue()[0]; + Excel attr = (Excel) entry.getValue()[1]; + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = parseDateToStr(dateFormat, val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + val = dataFormatHandlerAdapter(val, attr); + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param response 返回数据 + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName) + { + exportExcel(response, list, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param response 返回数据 + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(list, sheetName, title, Type.EXPORT); + exportExcel(response); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName) + { + importTemplateExcel(response, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(null, sheetName, title, Type.IMPORT); + exportExcel(response); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public void exportExcel(HttpServletResponse response) + { + try + { + writeSheet(); + wb.write(response.getOutputStream()); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + } + finally + { + IOUtils.closeQuietly(wb); + } + } + + /** + * 创建写入数据到Sheet + */ + public void writeSheet() + { + // 取出一共有多少个sheet. + int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); + for (int index = 0; index < sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(rownum); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType())) + { + for (Field subField : subFields) + { + Excel subExcel = subField.getAnnotation(Excel.class); + this.createHeadCell(subExcel, row, column++); + } + } + else + { + this.createHeadCell(excel, row, column++); + } + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + @SuppressWarnings("unchecked") + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + int rowNo = (1 + rownum) - startNo; + for (int i = startNo; i < endNo; i++) + { + rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; + row = sheet.createRow(rowNo); + // 得到导出对象. + T vo = (T) list.get(i); + Collection subList = null; + if (isSubList()) + { + if (isSubListValue(vo)) + { + subList = getListCellValue(vo); + subMergedLastRowNum = subMergedLastRowNum + subList.size(); + } + else + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + } + } + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) + { + boolean subFirst = false; + for (Object obj : subList) + { + if (subFirst) + { + rowNo++; + row = sheet.createRow(rowNo); + } + List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); + int subIndex = 0; + for (Field subField : subFields) + { + if (subField.isAnnotationPresent(Excel.class)) + { + subField.setAccessible(true); + Excel attr = subField.getAnnotation(Excel.class); + this.addCell(attr, row, (T) obj, subField, column + subIndex); + } + subIndex++; + } + subFirst = true; + } + this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); + } + else + { + this.addCell(excel, row, vo, field, column++); + } + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font titleFont = wb.createFont(); + titleFont.setFontName("Arial"); + titleFont.setFontHeightInPoints((short) 16); + titleFont.setBold(true); + style.setFont(titleFont); + styles.put("title", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + styles.putAll(annotationHeaderStyles(wb, styles)); + + styles.putAll(annotationDataStyles(wb)); + + return styles; + } + + /** + * 根据Excel注解创建表格头样式 + * + * @param wb 工作薄对象 + * @return 自定义样式列表 + */ + private Map annotationHeaderStyles(Workbook wb, Map styles) + { + Map headerStyles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); + if (!headerStyles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(excel.headerBackgroundColor().index); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(excel.headerColor().index); + style.setFont(headerFont); + headerStyles.put(key, style); + } + } + return headerStyles; + } + + /** + * 根据Excel注解创建表格列样式 + * + * @param wb 工作薄对象 + * @return 自定义样式列表 + */ + private Map annotationDataStyles(Workbook wb) + { + Map styles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); + if (!styles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.setAlignment(excel.align()); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setFillForegroundColor(excel.backgroundColor().getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + dataFont.setColor(excel.color().index); + style.setFont(dataFont); + styles.put(key, style); + } + } + return styles; + } + + /** + * 创建单元格 + */ + public Cell createHeadCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + if (isSubList()) + { + // 填充默认样式,防止合并单元格样式失效 + sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + if (attr.needMerge()) + { + sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); + } + } + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + String cellValue = Convert.toStr(value); + // 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。 + if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) + { + cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); + } + if (value instanceof Collection && StringUtils.equals("[]", cellValue)) + { + cellValue = StringUtils.EMPTY; + } + cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + if (StringUtils.isNotNull(value)) + { + cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + } + else if (ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (StringUtils.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获取画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获取图片类型,设置图片插入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) + { + if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) + { + // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到 + setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + else + { + // 提示信息或只能选择不能输入的列内容. + setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) + { + CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); + sheet.addMergedRegion(cellAddress); + } + cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(parseDateToStr(dateFormat, value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + cell.setCellValue(dataFormatHandlerAdapter(value, attr)); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示或选择框 + * + * @param sheet 表单 + * @param textlist 下拉框显示的内容 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了提示信息则鼠标放上去提示 + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框). + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) + { + String hideSheetName = "combo_" + firstCol + "_" + endCol; + Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 + for (int i = 0; i < textlist.length; i++) + { + hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); + } + // 创建名称,可被其他单元格引用 + Name name = wb.createName(); + name.setNameName(hideSheetName + "_data"); + name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了提示信息则鼠标放上去提示 + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + // 设置hiddenSheet隐藏 + wb.setSheetHidden(wb.getSheetIndex(hideSheet), true); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 数据处理器 + * + * @param value 数据值 + * @param excel 数据注解 + * @return + */ + public String dataFormatHandlerAdapter(Object value, Excel excel) + { + try + { + Object instance = excel.handler().newInstance(); + Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); + value = formatMethod.invoke(instance, value, excel.args()); + } + catch (Exception e) + { + log.error("不能格式化数据 " + excel.handler(), e.getMessage()); + } + return Convert.toStr(value); + } + + /** + * 合计统计信息 + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + Cell cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("合计"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.contains(".")) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = getFields(); + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 获取字段注解信息 + */ + public List getFields() + { + List fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + if (Collection.class.isAssignableFrom(field.getType())) + { + subMethod = getSubMethod(field.getName(), clazz); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class subClass = (Class) pt.getActualTypeArguments()[0]; + this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + } + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + } + } + } + } + return fields; + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = Math.max(maxHeight, excel.height()); + } + return (short) (maxHeight * 20); + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + this.sheet = wb.createSheet(); + wb.setSheetName(0, sheetName); + this.styles = createStyles(wb); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(int sheetNo, int index) + { + // 设置工作表的名称. + if (sheetNo > 1 && index > 0) + { + this.sheet = wb.createSheet(); + this.createTitle(); + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } + + /** + * 判断是否是空行 + * + * @param row 判断的行 + * @return + */ + private boolean isRowEmpty(Row row) + { + if (row == null) + { + return true; + } + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) + { + Cell cell = row.getCell(i); + if (cell != null && cell.getCellType() != CellType.BLANK) + { + return false; + } + } + return true; + } + + /** + * 格式化不同类型的日期对象 + * + * @param dateFormat 日期格式 + * @param val 被格式化的日期对象 + * @return 格式化后的日期字符 + */ + public String parseDateToStr(String dateFormat, Object val) + { + if (val == null) + { + return ""; + } + String str; + if (val instanceof Date) + { + str = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else if (val instanceof LocalDateTime) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val)); + } + else if (val instanceof LocalDate) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val)); + } + else + { + str = val.toString(); + } + return str; + } + + /** + * 是否有对象的子列表 + */ + public boolean isSubList() + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0; + } + + /** + * 是否有对象的子列表,集合不为空 + */ + public boolean isSubListValue(T vo) + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; + } + + /** + * 获取集合的值 + */ + public Collection getListCellValue(Object obj) + { + Object value; + try + { + value = subMethod.invoke(obj, new Object[] {}); + } + catch (Exception e) + { + return new ArrayList(); + } + return (Collection) value; + } + + /** + * 获取对象的子列表方法 + * + * @param name 名称 + * @param pojoClass 类对象 + * @return 子列表方法 + */ + public Method getSubMethod(String name, Class pojoClass) + { + StringBuffer getMethodName = new StringBuffer("get"); + getMethodName.append(name.substring(0, 1).toUpperCase()); + getMethodName.append(name.substring(1)); + Method method = null; + try + { + method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); + } + catch (Exception e) + { + log.error("获取对象异常{}", e.getMessage()); + } + return method; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/reflect/ReflectUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/reflect/ReflectUtils.java new file mode 100644 index 00000000..e25892fe --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/reflect/ReflectUtils.java @@ -0,0 +1,411 @@ +package com.yanzhu.common.core.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 com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.DateUtils; +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; + +/** + * 反射工具类. 提供调用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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sign/Base64.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sign/Base64.java new file mode 100644 index 00000000..290d99bb --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sign/Base64.java @@ -0,0 +1,291 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sql/SqlUtil.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sql/SqlUtil.java new file mode 100644 index 00000000..667f62b5 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/sql/SqlUtil.java @@ -0,0 +1,61 @@ +package com.yanzhu.common.core.utils.sql; + +import com.yanzhu.common.core.exception.UtilException; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * sql操作工具类 + * + * @author ruoyi + */ +public class SqlUtil +{ + /** + * 定义常用的 sql关键字 + */ + public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()"; + + /** + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) + */ + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new UtilException("参数不符合规范,不能进行查询"); + } + return value; + } + + /** + * 验证 order by 语法是否符合规范 + */ + public static boolean isValidOrderBySql(String value) + { + return value.matches(SQL_PATTERN); + } + + /** + * SQL关键字检查 + */ + public static void filterKeyword(String value) + { + if (StringUtils.isEmpty(value)) + { + return; + } + String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); + for (String sqlKeyword : sqlKeywords) + { + if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) + { + throw new UtilException("参数存在SQL注入风险"); + } + } + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/IdUtils.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/IdUtils.java new file mode 100644 index 00000000..19726997 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/IdUtils.java @@ -0,0 +1,49 @@ +package com.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/Seq.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/Seq.java new file mode 100644 index 00000000..876b3023 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/Seq.java @@ -0,0 +1,86 @@ +package com.yanzhu.common.core.utils.uuid; + +import java.util.concurrent.atomic.AtomicInteger; +import com.yanzhu.common.core.utils.DateUtils; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * @author ruoyi 序列生成类 + */ +public class Seq +{ + // 通用序列类型 + public static final String commSeqType = "COMMON"; + + // 上传序列类型 + public static final String uploadSeqType = "UPLOAD"; + + // 通用接口序列数 + private static AtomicInteger commSeq = new AtomicInteger(1); + + // 上传接口序列数 + private static AtomicInteger uploadSeq = new AtomicInteger(1); + + // 机器标识 + private static final String machineCode = "A"; + + /** + * 获取通用序列号 + * + * @return 序列值 + */ + public static String getId() + { + return getId(commSeqType); + } + + /** + * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串 + * + * @return 序列值 + */ + public static String getId(String type) + { + AtomicInteger atomicInt = commSeq; + if (uploadSeqType.equals(type)) + { + atomicInt = uploadSeq; + } + return getId(atomicInt, 3); + } + + /** + * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串 + * + * @param atomicInt 序列数 + * @param length 数值长度 + * @return 序列值 + */ + public static String getId(AtomicInteger atomicInt, int length) + { + String result = DateUtils.dateTimeNow(); + result += machineCode; + result += getSeq(atomicInt, length); + return result; + } + + /** + * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数 + * + * @return 序列值 + */ + private synchronized static String getSeq(AtomicInteger atomicInt, int length) + { + // 先取值再+1 + int value = atomicInt.getAndIncrement(); + + // 如果更新后值>=10 的 (length)幂次方则重置为1 + int maxSeq = (int) Math.pow(10, length); + if (atomicInt.get() >= maxSeq) + { + atomicInt.set(1); + } + // 转字符串,用0左补齐 + return StringUtils.padl(value, length); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/UUID.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/UUID.java new file mode 100644 index 00000000..46292622 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/utils/uuid/UUID.java @@ -0,0 +1,484 @@ +package com.yanzhu.common.core.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.yanzhu.common.core.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/controller/BaseController.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/controller/BaseController.java new file mode 100644 index 00000000..b8dc8fd0 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/controller/BaseController.java @@ -0,0 +1,143 @@ +package com.yanzhu.common.core.web.controller; + +import java.beans.PropertyEditorSupport; +import java.util.Date; +import java.util.List; + +import com.yanzhu.common.core.constant.HttpStatus; +import com.yanzhu.common.core.utils.DateUtils; +import com.yanzhu.common.core.utils.PageUtils; +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.PageInfo; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; + +/** + * web层通用数据处理 + * + * @author ruoyi + */ +public class BaseController +{ + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * 将前台传递过来的日期格式的字符串,自动转化为Date类型 + */ + @InitBinder + public void initBinder(WebDataBinder binder) + { + // Date 类型转换 + binder.registerCustomEditor(Date.class, new PropertyEditorSupport() + { + @Override + public void setAsText(String text) + { + setValue(DateUtils.parseDate(text)); + } + }); + } + + /** + * 设置请求分页数据 + */ + protected void startPage() + { + PageUtils.startPage(); + } + + /** + * 清理分页的线程变量 + */ + protected void clearPage() + { + PageUtils.clearPage(); + } + + /** + * 响应请求分页数据 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected TableDataInfo getDataTable(List list) + { + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setRows(list); + rspData.setMsg("查询成功"); + rspData.setTotal(new PageInfo(list).getTotal()); + return rspData; + } + + /** + * 返回成功 + */ + public AjaxResult success() + { + return AjaxResult.success(); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(String message) + { + return AjaxResult.success(message); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(Object data) + { + return AjaxResult.success(data); + } + + /** + * 返回失败消息 + */ + public AjaxResult error() + { + return AjaxResult.error(); + } + + /** + * 返回失败消息 + */ + public AjaxResult error(String message) + { + return AjaxResult.error(message); + } + + /** + * 返回警告消息 + */ + public AjaxResult warn(String message) + { + return AjaxResult.warn(message); + } + + /** + * 响应返回结果 + * + * @param rows 影响行数 + * @return 操作结果 + */ + protected AjaxResult toAjax(int rows) + { + return rows > 0 ? AjaxResult.success() : AjaxResult.error(); + } + + /** + * 响应返回结果 + * + * @param result 结果 + * @return 操作结果 + */ + protected AjaxResult toAjax(boolean result) + { + return result ? success() : error(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/AjaxResult.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/AjaxResult.java new file mode 100644 index 00000000..e7d67c9f --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/AjaxResult.java @@ -0,0 +1,206 @@ +package com.yanzhu.common.core.web.domain; + +import java.util.HashMap; +import java.util.Objects; +import com.yanzhu.common.core.constant.HttpStatus; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 操作消息提醒 + * + * @author ruoyi + */ +public class AjaxResult extends HashMap +{ + private static final long serialVersionUID = 1L; + + /** 状态码 */ + public static final String CODE_TAG = "code"; + + /** 返回内容 */ + public static final String MSG_TAG = "msg"; + + /** 数据对象 */ + public static final String DATA_TAG = "data"; + + /** + * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 + */ + public AjaxResult() + { + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + * @param data 数据对象 + */ + public AjaxResult(int code, String msg, Object data) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (StringUtils.isNotNull(data)) + { + super.put(DATA_TAG, data); + } + } + + /** + * 返回成功消息 + * + * @return 成功消息 + */ + public static AjaxResult success() + { + return AjaxResult.success("操作成功"); + } + + /** + * 返回成功数据 + * + * @return 成功消息 + */ + public static AjaxResult success(Object data) + { + return AjaxResult.success("操作成功", data); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @return 成功消息 + */ + public static AjaxResult success(String msg) + { + return AjaxResult.success(msg, null); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 成功消息 + */ + public static AjaxResult success(String msg, Object data) + { + return new AjaxResult(HttpStatus.SUCCESS, msg, data); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult warn(String msg) + { + return AjaxResult.warn(msg, null); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static AjaxResult warn(String msg, Object data) + { + return new AjaxResult(HttpStatus.WARN, msg, data); + } + + /** + * 返回错误消息 + * + * @return 错误消息 + */ + public static AjaxResult error() + { + return AjaxResult.error("操作失败"); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(String msg) + { + return AjaxResult.error(msg, null); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 错误消息 + */ + public static AjaxResult error(String msg, Object data) + { + return new AjaxResult(HttpStatus.ERROR, msg, data); + } + + /** + * 返回错误消息 + * + * @param code 状态码 + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(int code, String msg) + { + return new AjaxResult(code, msg, null); + } + + /** + * 是否为成功消息 + * + * @return 结果 + */ + public boolean isSuccess() + { + return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG)); + } + + /** + * 是否为错误消息 + * + * @return 结果 + */ + public boolean isError() + { + return !isSuccess(); + } + + /** + * 方便链式调用 + * + * @param key + * @param value + * @return + */ + @Override + public AjaxResult put(String key, Object value) + { + super.put(key, value); + return this; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/BaseEntity.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/BaseEntity.java new file mode 100644 index 00000000..394281f9 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/BaseEntity.java @@ -0,0 +1,129 @@ +package com.yanzhu.common.core.web.domain; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Entity基类 + * + * @author ruoyi + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 搜索值 */ + @JsonIgnore + private String searchValue; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** 备注 */ + private String remark; + + /** 选中页签 */ + private String activeName; + + /** 请求参数 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public String getSearchValue() + { + return searchValue; + } + + public void setSearchValue(String searchValue) + { + this.searchValue = searchValue; + } + + public String getCreateBy() + { + return createBy; + } + + public void setCreateBy(String createBy) + { + this.createBy = createBy; + } + + public Date getCreateTime() + { + return createTime; + } + + public void setCreateTime(Date createTime) + { + this.createTime = createTime; + } + + public String getUpdateBy() + { + return updateBy; + } + + public void setUpdateBy(String updateBy) + { + this.updateBy = updateBy; + } + + public Date getUpdateTime() + { + return updateTime; + } + + public void setUpdateTime(Date updateTime) + { + this.updateTime = updateTime; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } + + public String getActiveName() { + return activeName; + } + + public void setActiveName(String activeName) { + this.activeName = activeName; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/TreeEntity.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/TreeEntity.java new file mode 100644 index 00000000..8d9a62e9 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/domain/TreeEntity.java @@ -0,0 +1,79 @@ +package com.yanzhu.common.core.web.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/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/PageDomain.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/PageDomain.java new file mode 100644 index 00000000..7560e3a7 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/PageDomain.java @@ -0,0 +1,101 @@ +package com.yanzhu.common.core.web.page; + +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 分页数据 + * + * @author ruoyi + */ +public class PageDomain +{ + /** 当前记录起始索引 */ + private Integer pageNum; + + /** 每页显示记录数 */ + private Integer pageSize; + + /** 排序列 */ + private String orderByColumn; + + /** 排序的方向desc或者asc */ + private String isAsc = "asc"; + + /** 分页参数合理化 */ + private Boolean reasonable = true; + + public String getOrderBy() + { + if (StringUtils.isEmpty(orderByColumn)) + { + return ""; + } + return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; + } + + public Integer getPageNum() + { + return pageNum; + } + + public void setPageNum(Integer pageNum) + { + this.pageNum = pageNum; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public String getOrderByColumn() + { + return orderByColumn; + } + + public void setOrderByColumn(String orderByColumn) + { + this.orderByColumn = orderByColumn; + } + + public String getIsAsc() + { + return isAsc; + } + + public void setIsAsc(String isAsc) + { + if (StringUtils.isNotEmpty(isAsc)) + { + // 兼容前端排序类型 + if ("ascending".equals(isAsc)) + { + isAsc = "asc"; + } + else if ("descending".equals(isAsc)) + { + isAsc = "desc"; + } + this.isAsc = isAsc; + } + } + + public Boolean getReasonable() + { + if (StringUtils.isNull(reasonable)) + { + return Boolean.TRUE; + } + return reasonable; + } + + public void setReasonable(Boolean reasonable) + { + this.reasonable = reasonable; + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableDataInfo.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableDataInfo.java new file mode 100644 index 00000000..cc6d707c --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableDataInfo.java @@ -0,0 +1,85 @@ +package com.yanzhu.common.core.web.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; + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableSupport.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableSupport.java new file mode 100644 index 00000000..7affd9ae --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/web/page/TableSupport.java @@ -0,0 +1,56 @@ +package com.yanzhu.common.core.web.page; + +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.ServletUtils; + +/** + * 表格数据处理 + * + * @author ruoyi + */ +public class TableSupport +{ + /** + * 当前记录起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * 分页参数合理化 + */ + public static final String REASONABLE = "reasonable"; + + /** + * 封装分页对象 + */ + public static PageDomain getPageDomain() + { + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1)); + pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10)); + pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); + pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); + pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); + return pageDomain; + } + + public static PageDomain buildPageRequest() + { + return getPageDomain(); + } +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/Xss.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/Xss.java new file mode 100644 index 00000000..237eb89e --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/Xss.java @@ -0,0 +1,27 @@ +package com.yanzhu.common.core.xss; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义xss校验注解 + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER }) +@Constraint(validatedBy = { XssValidator.class }) +public @interface Xss +{ + String message() + + default "不允许任何脚本运行"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/XssValidator.java b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/XssValidator.java new file mode 100644 index 00000000..33c70329 --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/java/com/yanzhu/common/core/xss/XssValidator.java @@ -0,0 +1,34 @@ +package com.yanzhu.common.core.xss; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 自定义xss校验注解实现 + * + * @author ruoyi + */ +public class XssValidator implements ConstraintValidator +{ + private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />"; + + @Override + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) + { + if (StringUtils.isBlank(value)) + { + return true; + } + return !containsHtml(value); + } + + public static boolean containsHtml(String value) + { + Pattern pattern = Pattern.compile(HTML_PATTERN); + Matcher matcher = pattern.matcher(value); + return matcher.matches(); + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..b88790bc --- /dev/null +++ b/yanzhu-common/yanzhu-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.yanzhu.common.core.utils.SpringUtils diff --git a/yanzhu-common/yanzhu-common-datascope/pom.xml b/yanzhu-common/yanzhu-common-datascope/pom.xml new file mode 100644 index 00000000..a836d788 --- /dev/null +++ b/yanzhu-common/yanzhu-common-datascope/pom.xml @@ -0,0 +1,27 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-datascope + + + yanzhu-common-datascope权限范围 + + + + + + + com.yanzhu + yanzhu-common-security + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/annotation/DataScope.java b/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/annotation/DataScope.java new file mode 100644 index 00000000..7324bfa7 --- /dev/null +++ b/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/annotation/DataScope.java @@ -0,0 +1,33 @@ +package com.yanzhu.common.datascope.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 ""; + + /** + * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@RequiresPermissions获取,多个权限用逗号分隔开来 + */ + public String permission() default ""; +} diff --git a/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/aspect/DataScopeAspect.java b/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/aspect/DataScopeAspect.java new file mode 100644 index 00000000..d2c89e6a --- /dev/null +++ b/yanzhu-common/yanzhu-common-datascope/src/main/java/com/yanzhu/common/datascope/aspect/DataScopeAspect.java @@ -0,0 +1,168 @@ +package com.yanzhu.common.datascope.aspect; + +import java.util.ArrayList; +import java.util.List; + +import com.yanzhu.common.datascope.annotation.DataScope; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.context.SecurityContextHolder; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.domain.BaseEntity; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.api.model.LoginUser; + +/** + * 数据过滤处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class DataScopeAspect +{ + /** + * 全部数据权限 + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable + { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) + { + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getSysUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), SecurityContextHolder.getPermission()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias(), permission); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param deptAlias 部门别名 + * @param userAlias 用户别名 + * @param permission 权限字符 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission) + { + StringBuilder sqlString = new StringBuilder(); + List conditions = new ArrayList(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) + { + continue; + } + if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) + && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) + { + continue; + } + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + break; + } + else if (DATA_SCOPE_CUSTOM.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } + else if (DATA_SCOPE_DEPT.equals(dataScope)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } + else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } + else if (DATA_SCOPE_SELF.equals(dataScope)) + { + if (StringUtils.isNotBlank(userAlias)) + { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } + else + { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + + if (StringUtils.isNotBlank(sqlString.toString())) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } +} diff --git a/yanzhu-common/yanzhu-common-datascope/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-datascope/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..f750aeff --- /dev/null +++ b/yanzhu-common/yanzhu-common-datascope/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.yanzhu.common.datascope.aspect.DataScopeAspect diff --git a/yanzhu-common/yanzhu-common-datasource/pom.xml b/yanzhu-common/yanzhu-common-datasource/pom.xml new file mode 100644 index 00000000..d8933f3d --- /dev/null +++ b/yanzhu-common/yanzhu-common-datasource/pom.xml @@ -0,0 +1,35 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-datasource + + + yanzhu-common-datasource多数据源 + + + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${dynamic-ds.version} + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Master.java b/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Master.java new file mode 100644 index 00000000..d0d54fbb --- /dev/null +++ b/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Master.java @@ -0,0 +1,22 @@ +package com.yanzhu.common.datasource.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.baomidou.dynamic.datasource.annotation.DS; + +/** + * 主库数据源 + * + * @author ruoyi + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@DS("master") +public @interface Master +{ + +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Slave.java b/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Slave.java new file mode 100644 index 00000000..c3f0babc --- /dev/null +++ b/yanzhu-common/yanzhu-common-datasource/src/main/java/com/yanzhu/common/datasource/annotation/Slave.java @@ -0,0 +1,22 @@ +package com.yanzhu.common.datasource.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.baomidou.dynamic.datasource.annotation.DS; + +/** + * 从库数据源 + * + * @author ruoyi + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@DS("slave") +public @interface Slave +{ + +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-log/pom.xml b/yanzhu-common/yanzhu-common-log/pom.xml new file mode 100644 index 00000000..ee55dd7c --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/pom.xml @@ -0,0 +1,27 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-log + + + yanzhu-common-log日志记录 + + + + + + + com.yanzhu + yanzhu-common-security + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/annotation/Log.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/annotation/Log.java new file mode 100644 index 00000000..f9549d34 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/annotation/Log.java @@ -0,0 +1,51 @@ +package com.yanzhu.common.log.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.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.log.enums.OperatorType; + +/** + * 自定义操作日志记录注解 + * + * @author ruoyi + * + */ +@Target({ ElementType.PARAMETER, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log +{ + /** + * 模块 + */ + public String title() default ""; + + /** + * 功能 + */ + public BusinessType businessType() default BusinessType.OTHER; + + /** + * 操作人类别 + */ + public OperatorType operatorType() default OperatorType.MANAGE; + + /** + * 是否保存请求的参数 + */ + public boolean isSaveRequestData() default true; + + /** + * 是否保存响应的参数 + */ + public boolean isSaveResponseData() default true; + + /** + * 排除指定的请求参数 + */ + public String[] excludeParamNames() default {}; +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/aspect/LogAspect.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/aspect/LogAspect.java new file mode 100644 index 00000000..2b4fea9d --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/aspect/LogAspect.java @@ -0,0 +1,250 @@ +package com.yanzhu.common.log.aspect; + +import java.util.Collection; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessStatus; +import com.yanzhu.common.log.filter.PropertyPreExcludeFilter; +import com.yanzhu.common.log.service.AsyncLogService; +import org.apache.commons.lang3.ArrayUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.NamedThreadLocal; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import com.alibaba.fastjson2.JSON; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.ip.IpUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysOperLog; + +/** + * 操作日志记录处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class LogAspect +{ + private static final Logger log = LoggerFactory.getLogger(LogAspect.class); + + /** 排除敏感属性字段 */ + public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; + + /** 计算操作消耗时间 */ + private static final ThreadLocal TIME_THREADLOCAL = new NamedThreadLocal("Cost Time"); + + @Autowired + private AsyncLogService asyncLogService; + + /** + * 处理请求前执行 + */ + @Before(value = "@annotation(controllerLog)") + public void boBefore(JoinPoint joinPoint, Log controllerLog) + { + TIME_THREADLOCAL.set(System.currentTimeMillis()); + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) + { + handleLog(joinPoint, controllerLog, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) + { + handleLog(joinPoint, controllerLog, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) + { + try + { + // *========数据库日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = IpUtils.getIpAddr(); + operLog.setOperIp(ip); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); + String username = SecurityUtils.getUsername(); + if (StringUtils.isNotBlank(username)) + { + operLog.setOperName(username); + } + + if (e != null) + { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 设置消耗时间 + operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get()); + // 保存数据库 + asyncLogService.saveSysLog(operLog); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + finally + { + TIME_THREADLOCAL.remove(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception + { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置操作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) + { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog, log.excludeParamNames()); + } + // 是否需要保存response,参数和值 + if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) + { + operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception + { + String requestMethod = operLog.getRequestMethod(); + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); + if (StringUtils.isEmpty(paramsMap) + && (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))) + { + String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000)); + } + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (Object o : paramsArray) + { + if (StringUtils.isNotNull(o) && !isFilterObject(o)) + { + try + { + String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); + params += jsonObj.toString() + " "; + } + catch (Exception e) + { + } + } + } + } + return params.trim(); + } + + /** + * 忽略敏感属性 + */ + public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames) + { + return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames)); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Object value : collection) + { + return value instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Object value : map.entrySet()) + { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessStatus.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessStatus.java new file mode 100644 index 00000000..690090cc --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessStatus.java @@ -0,0 +1,20 @@ +package com.yanzhu.common.log.enums; + +/** + * 操作状态 + * + * @author ruoyi + * + */ +public enum BusinessStatus +{ + /** + * 成功 + */ + SUCCESS, + + /** + * 失败 + */ + FAIL, +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessType.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessType.java new file mode 100644 index 00000000..f238ff48 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/BusinessType.java @@ -0,0 +1,59 @@ +package com.yanzhu.common.log.enums; + +/** + * 业务操作类型 + * + * @author ruoyi + */ +public enum BusinessType +{ + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + + /** + * 授权 + */ + GRANT, + + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + + /** + * 强退 + */ + FORCE, + + /** + * 生成代码 + */ + GENCODE, + + /** + * 清空数据 + */ + CLEAN, +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/OperatorType.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/OperatorType.java new file mode 100644 index 00000000..ade37196 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/enums/OperatorType.java @@ -0,0 +1,24 @@ +package com.yanzhu.common.log.enums; + +/** + * 操作人类别 + * + * @author ruoyi + */ +public enum OperatorType +{ + /** + * 其它 + */ + OTHER, + + /** + * 后台用户 + */ + MANAGE, + + /** + * 手机端用户 + */ + MOBILE +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/filter/PropertyPreExcludeFilter.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/filter/PropertyPreExcludeFilter.java new file mode 100644 index 00000000..d12148e9 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/filter/PropertyPreExcludeFilter.java @@ -0,0 +1,24 @@ +package com.yanzhu.common.log.filter; + +import com.alibaba.fastjson2.filter.SimplePropertyPreFilter; + +/** + * 排除JSON敏感属性 + * + * @author ruoyi + */ +public class PropertyPreExcludeFilter extends SimplePropertyPreFilter +{ + public PropertyPreExcludeFilter() + { + } + + public PropertyPreExcludeFilter addExcludes(String... filters) + { + for (int i = 0; i < filters.length; i++) + { + this.getExcludes().add(filters[i]); + } + return this; + } +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/service/AsyncLogService.java b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/service/AsyncLogService.java new file mode 100644 index 00000000..68c56de3 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/java/com/yanzhu/common/log/service/AsyncLogService.java @@ -0,0 +1,29 @@ +package com.yanzhu.common.log.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.system.api.RemoteLogService; +import com.yanzhu.system.api.domain.SysOperLog; + +/** + * 异步调用日志服务 + * + * @author ruoyi + */ +@Service +public class AsyncLogService +{ + @Autowired + private RemoteLogService remoteLogService; + + /** + * 保存系统日志记录 + */ + @Async + public void saveSysLog(SysOperLog sysOperLog) + { + remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER); + } +} diff --git a/yanzhu-common/yanzhu-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..f50acf38 --- /dev/null +++ b/yanzhu-common/yanzhu-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.yanzhu.common.log.service.AsyncLogService +com.yanzhu.common.log.aspect.LogAspect diff --git a/yanzhu-common/yanzhu-common-mapper/pom.xml b/yanzhu-common/yanzhu-common-mapper/pom.xml new file mode 100644 index 00000000..9ec699b0 --- /dev/null +++ b/yanzhu-common/yanzhu-common-mapper/pom.xml @@ -0,0 +1,33 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-mapper + + + yanzhu-common-mapper + + + + + + + com.yanzhu + yanzhu-common-security + + + org.projectlombok + lombok + provided + + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/mapper/domain/init b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/mapper/domain/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-common/yanzhu-common-redis/pom.xml b/yanzhu-common/yanzhu-common-redis/pom.xml new file mode 100644 index 00000000..371bda26 --- /dev/null +++ b/yanzhu-common/yanzhu-common-redis/pom.xml @@ -0,0 +1,33 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-redis + + + yanzhu-common-redis缓存服务 + + + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + com.yanzhu + yanzhu-common-core + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/FastJson2JsonRedisSerializer.java b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/FastJson2JsonRedisSerializer.java new file mode 100644 index 00000000..7e94610f --- /dev/null +++ b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/FastJson2JsonRedisSerializer.java @@ -0,0 +1,49 @@ +package com.yanzhu.common.redis.configure; + +import java.nio.charset.Charset; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; + +/** + * Redis使用FastJson序列化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + + public FastJson2JsonRedisSerializer(Class clazz) + { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException + { + if (t == null) + { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException + { + if (bytes == null || bytes.length <= 0) + { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} diff --git a/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/RedisConfig.java b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/RedisConfig.java new file mode 100644 index 00000000..1d619ac6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/configure/RedisConfig.java @@ -0,0 +1,43 @@ +package com.yanzhu.common.redis.configure; + +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +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.serializer.StringRedisSerializer; + +/** + * redis配置 + * + * @author ruoyi + */ +@Configuration +@EnableCaching +@AutoConfigureBefore(RedisAutoConfiguration.class) +public class RedisConfig extends CachingConfigurerSupport +{ + @Bean + @SuppressWarnings(value = { "unchecked", "rawtypes" }) + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) + { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + + // Hash的key也采用StringRedisSerializer的序列化方式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } +} diff --git a/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/service/RedisService.java b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/service/RedisService.java new file mode 100644 index 00000000..3a1e33da --- /dev/null +++ b/yanzhu-common/yanzhu-common-redis/src/main/java/com/yanzhu/common/redis/service/RedisService.java @@ -0,0 +1,268 @@ +package com.yanzhu.common.redis.service; + +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 RedisService +{ + @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 Long timeout, final TimeUnit timeUnit) + { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) + { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) + { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获取有效时间 + * + * @param key Redis键 + * @return 有效时间 + */ + public long getExpire(final String key) + { + return redisTemplate.getExpire(key); + } + + /** + * 判断 key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public Boolean hasKey(String key) + { + return redisTemplate.hasKey(key); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) + { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) + { + return redisTemplate.delete(key); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public boolean deleteObject(final Collection collection) + { + return redisTemplate.delete(collection) > 0; + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @param dataList 待缓存的List数据 + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) + { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public List getCacheList(final String key) + { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public BoundSetOperations setCacheSet(final String key, final Set dataSet) + { + BoundSetOperations setOperation = redisTemplate.boundSetOps(key); + Iterator it = dataSet.iterator(); + while (it.hasNext()) + { + setOperation.add(it.next()); + } + return setOperation; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) + { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) + { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) + { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) + { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) + { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) + { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 删除Hash中的某条数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return 是否成功 + */ + public boolean deleteCacheMapValue(final String key, final String hKey) + { + return redisTemplate.opsForHash().delete(key, hKey) > 0; + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) + { + return redisTemplate.keys(pattern); + } +} diff --git a/yanzhu-common/yanzhu-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..d32a76fa --- /dev/null +++ b/yanzhu-common/yanzhu-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.yanzhu.common.redis.configure.RedisConfig +com.yanzhu.common.redis.service.RedisService diff --git a/yanzhu-common/yanzhu-common-seata/pom.xml b/yanzhu-common/yanzhu-common-seata/pom.xml new file mode 100644 index 00000000..7d0223a6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-seata/pom.xml @@ -0,0 +1,27 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-seata + + + yanzhu-common-seata分布式事务 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-seata + + + + \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-security/pom.xml b/yanzhu-common/yanzhu-common-security/pom.xml new file mode 100644 index 00000000..ee89269e --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/pom.xml @@ -0,0 +1,39 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-security + + + yanzhu-common-security安全模块 + + + + + + + org.springframework + spring-webmvc + + + + + com.yanzhu + yanzhu-api-system + + + + + com.yanzhu + yanzhu-common-redis + + + + + diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableCustomConfig.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableCustomConfig.java new file mode 100644 index 00000000..bf7dc5ee --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableCustomConfig.java @@ -0,0 +1,31 @@ +package com.yanzhu.common.security.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 org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.context.annotation.Import; +import org.springframework.scheduling.annotation.EnableAsync; +import com.yanzhu.common.security.config.ApplicationConfig; +import com.yanzhu.common.security.feign.FeignAutoConfiguration; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +// 表示通过aop框架暴露该代理对象,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// 指定要扫描的Mapper类的包的路径 +@MapperScan("com.yanzhu.**.mapper") +// 开启线程异步执行 +@EnableAsync +// 自动加载类 +@Import({ ApplicationConfig.class, FeignAutoConfiguration.class }) +public @interface EnableCustomConfig +{ + +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableRyFeignClients.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableRyFeignClients.java new file mode 100644 index 00000000..a5810717 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/EnableRyFeignClients.java @@ -0,0 +1,27 @@ +package com.yanzhu.common.security.annotation; + +import org.springframework.cloud.openfeign.EnableFeignClients; +import java.lang.annotation.*; + +/** + * 自定义feign注解 + * 添加basePackages路径 + * + * @author ruoyi + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@EnableFeignClients +public @interface EnableRyFeignClients +{ + String[] value() default {}; + + String[] basePackages() default { "com.yanzhu" }; + + Class[] basePackageClasses() default {}; + + Class[] defaultConfiguration() default {}; + + Class[] clients() default {}; +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/InnerAuth.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/InnerAuth.java new file mode 100644 index 00000000..0dab7cbe --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/InnerAuth.java @@ -0,0 +1,19 @@ +package com.yanzhu.common.security.annotation; + +import java.lang.annotation.*; + +/** + * 内部认证注解 + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface InnerAuth +{ + /** + * 是否校验用户信息 + */ + boolean isUser() default false; +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/Logical.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/Logical.java new file mode 100644 index 00000000..096a2ad2 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/Logical.java @@ -0,0 +1,20 @@ +package com.yanzhu.common.security.annotation; + +/** + * 权限注解的验证模式 + * + * @author ruoyi + * + */ +public enum Logical +{ + /** + * 必须具有所有的元素 + */ + AND, + + /** + * 只需具有其中一个元素 + */ + OR +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresLogin.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresLogin.java new file mode 100644 index 00000000..2a32ea75 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresLogin.java @@ -0,0 +1,18 @@ +package com.yanzhu.common.security.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 登录认证:只有登录之后才能进入该方法 + * + * @author ruoyi + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface RequiresLogin +{ +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresPermissions.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresPermissions.java new file mode 100644 index 00000000..e0416f8f --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresPermissions.java @@ -0,0 +1,27 @@ +package com.yanzhu.common.security.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 权限认证:必须具有指定权限才能进入该方法 + * + * @author ruoyi + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface RequiresPermissions +{ + /** + * 需要校验的权限码 + */ + String[] value() default {}; + + /** + * 验证模式:AND | OR,默认AND + */ + Logical logical() default Logical.AND; +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresRoles.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresRoles.java new file mode 100644 index 00000000..97f13e62 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/annotation/RequiresRoles.java @@ -0,0 +1,26 @@ +package com.yanzhu.common.security.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 角色认证:必须具有指定角色标识才能进入该方法 + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface RequiresRoles +{ + /** + * 需要校验的角色标识 + */ + String[] value() default {}; + + /** + * 验证逻辑:AND | OR,默认AND + */ + Logical logical() default Logical.AND; +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/InnerAuthAspect.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/InnerAuthAspect.java new file mode 100644 index 00000000..1c8aac48 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/InnerAuthAspect.java @@ -0,0 +1,51 @@ +package com.yanzhu.common.security.aspect; + +import com.yanzhu.common.security.annotation.InnerAuth; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.exception.InnerAuthException; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 内部服务调用验证处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class InnerAuthAspect implements Ordered +{ + @Around("@annotation(innerAuth)") + public Object innerAround(ProceedingJoinPoint point, InnerAuth innerAuth) throws Throwable + { + String source = ServletUtils.getRequest().getHeader(SecurityConstants.FROM_SOURCE); + // 内部请求验证 + if (!StringUtils.equals(SecurityConstants.INNER, source)) + { + throw new InnerAuthException("没有内部访问权限,不允许访问"); + } + + String userid = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID); + String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME); + // 用户信息验证 + if (innerAuth.isUser() && (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))) + { + throw new InnerAuthException("没有设置用户信息,不允许访问 "); + } + return point.proceed(); + } + + /** + * 确保在权限认证aop执行前执行 + */ + @Override + public int getOrder() + { + return Ordered.HIGHEST_PRECEDENCE + 1; + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/PreAuthorizeAspect.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/PreAuthorizeAspect.java new file mode 100644 index 00000000..c733317e --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/aspect/PreAuthorizeAspect.java @@ -0,0 +1,98 @@ +package com.yanzhu.common.security.aspect; + +import java.lang.reflect.Method; + +import com.yanzhu.common.security.annotation.RequiresLogin; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.annotation.RequiresRoles; +import com.yanzhu.common.security.auth.AuthUtil; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +/** + * 基于 Spring Aop 的注解鉴权 + * + * @author kong + */ +@Aspect +@Component +public class PreAuthorizeAspect +{ + /** + * 构建 + */ + public PreAuthorizeAspect() + { + } + + /** + * 定义AOP签名 (切入所有使用鉴权注解的方法) + */ + public static final String POINTCUT_SIGN = " @annotation(com.yanzhu.common.security.annotation.RequiresLogin) || " + + "@annotation(com.yanzhu.common.security.annotation.RequiresPermissions) || " + + "@annotation(com.yanzhu.common.security.annotation.RequiresRoles)"; + + /** + * 声明AOP签名 + */ + @Pointcut(POINTCUT_SIGN) + public void pointcut() + { + } + + /** + * 环绕切入 + * + * @param joinPoint 切面对象 + * @return 底层方法执行后的返回值 + * @throws Throwable 底层方法抛出的异常 + */ + @Around("pointcut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable + { + // 注解鉴权 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + checkMethodAnnotation(signature.getMethod()); + try + { + // 执行原有逻辑 + Object obj = joinPoint.proceed(); + return obj; + } + catch (Throwable e) + { + throw e; + } + } + + /** + * 对一个Method对象进行注解检查 + */ + public void checkMethodAnnotation(Method method) + { + // 校验 @RequiresLogin 注解 + RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class); + if (requiresLogin != null) + { + AuthUtil.checkLogin(); + } + + // 校验 @RequiresRoles 注解 + RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class); + if (requiresRoles != null) + { + AuthUtil.checkRole(requiresRoles); + } + + // 校验 @RequiresPermissions 注解 + RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class); + if (requiresPermissions != null) + { + AuthUtil.checkPermi(requiresPermissions); + } + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthLogic.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthLogic.java new file mode 100644 index 00000000..ff822589 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthLogic.java @@ -0,0 +1,374 @@ +package com.yanzhu.common.security.auth; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.util.PatternMatchUtils; +import com.yanzhu.common.core.context.SecurityContextHolder; +import com.yanzhu.common.core.exception.auth.NotLoginException; +import com.yanzhu.common.core.exception.auth.NotPermissionException; +import com.yanzhu.common.core.exception.auth.NotRoleException; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.annotation.Logical; +import com.yanzhu.common.security.annotation.RequiresLogin; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.annotation.RequiresRoles; +import com.yanzhu.common.security.service.TokenService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.model.LoginUser; + +/** + * Token 权限验证,逻辑实现类 + * + * @author ruoyi + */ +public class AuthLogic +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + public TokenService tokenService = SpringUtils.getBean(TokenService.class); + + /** + * 会话注销 + */ + public void logout() + { + String token = SecurityUtils.getToken(); + if (token == null) + { + return; + } + logoutByToken(token); + } + + /** + * 会话注销,根据指定Token + */ + public void logoutByToken(String token) + { + tokenService.delLoginUser(token); + } + + /** + * 检验用户是否已经登录,如未登录,则抛出异常 + */ + public void checkLogin() + { + getLoginUser(); + } + + /** + * 获取当前用户缓存信息, 如果未登录,则抛出异常 + * + * @return 用户缓存信息 + */ + public LoginUser getLoginUser() + { + String token = SecurityUtils.getToken(); + if (token == null) + { + throw new NotLoginException("未提供token"); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null) + { + throw new NotLoginException("无效的token"); + } + return loginUser; + } + + /** + * 获取当前用户缓存信息, 如果未登录,则抛出异常 + * + * @param token 前端传递的认证信息 + * @return 用户缓存信息 + */ + public LoginUser getLoginUser(String token) + { + return tokenService.getLoginUser(token); + } + + /** + * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存 + * + * @param loginUser 当前用户信息 + */ + public void verifyLoginUserExpire(LoginUser loginUser) + { + tokenService.verifyToken(loginUser); + } + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) + { + return hasPermi(getPermiList(), permission); + } + + /** + * 验证用户是否具备某权限, 如果验证未通过,则抛出异常: NotPermissionException + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public void checkPermi(String permission) + { + if (!hasPermi(getPermiList(), permission)) + { + throw new NotPermissionException(permission); + } + } + + /** + * 根据注解(@RequiresPermissions)鉴权, 如果验证未通过,则抛出异常: NotPermissionException + * + * @param requiresPermissions 注解对象 + */ + public void checkPermi(RequiresPermissions requiresPermissions) + { + SecurityContextHolder.setPermission(StringUtils.join(requiresPermissions.value(), ",")); + if (requiresPermissions.logical() == Logical.AND) + { + checkPermiAnd(requiresPermissions.value()); + } + else + { + checkPermiOr(requiresPermissions.value()); + } + } + + /** + * 验证用户是否含有指定权限,必须全部拥有 + * + * @param permissions 权限列表 + */ + public void checkPermiAnd(String... permissions) + { + Set permissionList = getPermiList(); + for (String permission : permissions) + { + if (!hasPermi(permissionList, permission)) + { + throw new NotPermissionException(permission); + } + } + } + + /** + * 验证用户是否含有指定权限,只需包含其中一个 + * + * @param permissions 权限码数组 + */ + public void checkPermiOr(String... permissions) + { + Set permissionList = getPermiList(); + for (String permission : permissions) + { + if (hasPermi(permissionList, permission)) + { + return; + } + } + if (permissions.length > 0) + { + throw new NotPermissionException(permissions); + } + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色标识 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) + { + return hasRole(getRoleList(), role); + } + + /** + * 判断用户是否拥有某个角色, 如果验证未通过,则抛出异常: NotRoleException + * + * @param role 角色标识 + */ + public void checkRole(String role) + { + if (!hasRole(role)) + { + throw new NotRoleException(role); + } + } + + /** + * 根据注解(@RequiresRoles)鉴权 + * + * @param requiresRoles 注解对象 + */ + public void checkRole(RequiresRoles requiresRoles) + { + if (requiresRoles.logical() == Logical.AND) + { + checkRoleAnd(requiresRoles.value()); + } + else + { + checkRoleOr(requiresRoles.value()); + } + } + + /** + * 验证用户是否含有指定角色,必须全部拥有 + * + * @param roles 角色标识数组 + */ + public void checkRoleAnd(String... roles) + { + Set roleList = getRoleList(); + for (String role : roles) + { + if (!hasRole(roleList, role)) + { + throw new NotRoleException(role); + } + } + } + + /** + * 验证用户是否含有指定角色,只需包含其中一个 + * + * @param roles 角色标识数组 + */ + public void checkRoleOr(String... roles) + { + Set roleList = getRoleList(); + for (String role : roles) + { + if (hasRole(roleList, role)) + { + return; + } + } + if (roles.length > 0) + { + throw new NotRoleException(roles); + } + } + + /** + * 根据注解(@RequiresLogin)鉴权 + * + * @param at 注解对象 + */ + public void checkByAnnotation(RequiresLogin at) + { + this.checkLogin(); + } + + /** + * 根据注解(@RequiresRoles)鉴权 + * + * @param at 注解对象 + */ + public void checkByAnnotation(RequiresRoles at) + { + String[] roleArray = at.value(); + if (at.logical() == Logical.AND) + { + this.checkRoleAnd(roleArray); + } + else + { + this.checkRoleOr(roleArray); + } + } + + /** + * 根据注解(@RequiresPermissions)鉴权 + * + * @param at 注解对象 + */ + public void checkByAnnotation(RequiresPermissions at) + { + String[] permissionArray = at.value(); + if (at.logical() == Logical.AND) + { + this.checkPermiAnd(permissionArray); + } + else + { + this.checkPermiOr(permissionArray); + } + } + + /** + * 获取当前账号的角色列表 + * + * @return 角色列表 + */ + public Set getRoleList() + { + try + { + LoginUser loginUser = getLoginUser(); + return loginUser.getRoles(); + } + catch (Exception e) + { + return new HashSet<>(); + } + } + + /** + * 获取当前账号的权限列表 + * + * @return 权限列表 + */ + public Set getPermiList() + { + try + { + LoginUser loginUser = getLoginUser(); + return loginUser.getPermissions(); + } + catch (Exception e) + { + return new HashSet<>(); + } + } + + /** + * 判断是否包含权限 + * + * @param authorities 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(Collection authorities, String permission) + { + return authorities.stream().filter(StringUtils::hasText) + .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission)); + } + + /** + * 判断是否包含角色 + * + * @param roles 角色列表 + * @param role 角色 + * @return 用户是否具备某角色权限 + */ + public boolean hasRole(Collection roles, String role) + { + return roles.stream().filter(StringUtils::hasText) + .anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role)); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthUtil.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthUtil.java new file mode 100644 index 00000000..2e1a6260 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/auth/AuthUtil.java @@ -0,0 +1,167 @@ +package com.yanzhu.common.security.auth; + +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.annotation.RequiresRoles; +import com.yanzhu.system.api.model.LoginUser; + +/** + * Token 权限验证工具类 + * + * @author ruoyi + */ +public class AuthUtil +{ + /** + * 底层的 AuthLogic 对象 + */ + public static AuthLogic authLogic = new AuthLogic(); + + /** + * 会话注销 + */ + public static void logout() + { + authLogic.logout(); + } + + /** + * 会话注销,根据指定Token + * + * @param token 指定token + */ + public static void logoutByToken(String token) + { + authLogic.logoutByToken(token); + } + + /** + * 检验当前会话是否已经登录,如未登录,则抛出异常 + */ + public static void checkLogin() + { + authLogic.checkLogin(); + } + + /** + * 获取当前登录用户信息 + * + * @param token 指定token + * @return 用户信息 + */ + public static LoginUser getLoginUser(String token) + { + return authLogic.getLoginUser(token); + } + + /** + * 验证当前用户有效期 + * + * @param loginUser 用户信息 + */ + public static void verifyLoginUserExpire(LoginUser loginUser) + { + authLogic.verifyLoginUserExpire(loginUser); + } + + /** + * 当前账号是否含有指定角色标识, 返回true或false + * + * @param role 角色标识 + * @return 是否含有指定角色标识 + */ + public static boolean hasRole(String role) + { + return authLogic.hasRole(role); + } + + /** + * 当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException + * + * @param role 角色标识 + */ + public static void checkRole(String role) + { + authLogic.checkRole(role); + } + + /** + * 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotRoleException + * + * @param requiresRoles 角色权限注解 + */ + public static void checkRole(RequiresRoles requiresRoles) + { + authLogic.checkRole(requiresRoles); + } + + /** + * 当前账号是否含有指定角色标识 [指定多个,必须全部验证通过] + * + * @param roles 角色标识数组 + */ + public static void checkRoleAnd(String... roles) + { + authLogic.checkRoleAnd(roles); + } + + /** + * 当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] + * + * @param roles 角色标识数组 + */ + public static void checkRoleOr(String... roles) + { + authLogic.checkRoleOr(roles); + } + + /** + * 当前账号是否含有指定权限, 返回true或false + * + * @param permission 权限码 + * @return 是否含有指定权限 + */ + public static boolean hasPermi(String permission) + { + return authLogic.hasPermi(permission); + } + + /** + * 当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException + * + * @param permission 权限码 + */ + public static void checkPermi(String permission) + { + authLogic.checkPermi(permission); + } + + /** + * 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotPermissionException + * + * @param requiresPermissions 权限注解 + */ + public static void checkPermi(RequiresPermissions requiresPermissions) + { + authLogic.checkPermi(requiresPermissions); + } + + /** + * 当前账号是否含有指定权限 [指定多个,必须全部验证通过] + * + * @param permissions 权限码数组 + */ + public static void checkPermiAnd(String... permissions) + { + authLogic.checkPermiAnd(permissions); + } + + /** + * 当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] + * + * @param permissions 权限码数组 + */ + public static void checkPermiOr(String... permissions) + { + authLogic.checkPermiOr(permissions); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/ApplicationConfig.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/ApplicationConfig.java new file mode 100644 index 00000000..6b397c2e --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/ApplicationConfig.java @@ -0,0 +1,22 @@ +package com.yanzhu.common.security.config; + +import java.util.TimeZone; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; + +/** + * 系统配置 + * + * @author ruoyi + */ +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/WebMvcConfig.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/WebMvcConfig.java new file mode 100644 index 00000000..957fb895 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/config/WebMvcConfig.java @@ -0,0 +1,33 @@ +package com.yanzhu.common.security.config; + +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.yanzhu.common.security.interceptor.HeaderInterceptor; + +/** + * 拦截器配置 + * + * @author ruoyi + */ +public class WebMvcConfig implements WebMvcConfigurer +{ + /** 不需要拦截地址 */ + public static final String[] excludeUrls = { "/login", "/logout", "/refresh" }; + + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(getHeaderInterceptor()) + .addPathPatterns("/**") + .excludePathPatterns(excludeUrls) + .order(-10); + } + + /** + * 自定义请求头拦截器 + */ + public HeaderInterceptor getHeaderInterceptor() + { + return new HeaderInterceptor(); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignAutoConfiguration.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignAutoConfiguration.java new file mode 100644 index 00000000..f7ab2f11 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignAutoConfiguration.java @@ -0,0 +1,20 @@ +package com.yanzhu.common.security.feign; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import feign.RequestInterceptor; + +/** + * Feign 配置注册 + * + * @author ruoyi + **/ +@Configuration +public class FeignAutoConfiguration +{ + @Bean + public RequestInterceptor requestInterceptor() + { + return new FeignRequestInterceptor(); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignRequestInterceptor.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignRequestInterceptor.java new file mode 100644 index 00000000..766d9b71 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/feign/FeignRequestInterceptor.java @@ -0,0 +1,54 @@ +package com.yanzhu.common.security.feign; + +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.ip.IpUtils; +import feign.RequestInterceptor; +import feign.RequestTemplate; + +/** + * feign 请求拦截器 + * + * @author ruoyi + */ +@Component +public class FeignRequestInterceptor implements RequestInterceptor +{ + @Override + public void apply(RequestTemplate requestTemplate) + { + HttpServletRequest httpServletRequest = ServletUtils.getRequest(); + if (StringUtils.isNotNull(httpServletRequest)) + { + Map headers = ServletUtils.getHeaders(httpServletRequest); + // 传递用户信息请求头,防止丢失 + String userId = headers.get(SecurityConstants.DETAILS_USER_ID); + if (StringUtils.isNotEmpty(userId)) + { + requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId); + } + String userKey = headers.get(SecurityConstants.USER_KEY); + if (StringUtils.isNotEmpty(userKey)) + { + requestTemplate.header(SecurityConstants.USER_KEY, userKey); + } + String userName = headers.get(SecurityConstants.DETAILS_USERNAME); + if (StringUtils.isNotEmpty(userName)) + { + requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName); + } + String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER); + if (StringUtils.isNotEmpty(authentication)) + { + requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication); + } + + // 配置客户端IP + requestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr()); + } + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/handler/GlobalExceptionHandler.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/handler/GlobalExceptionHandler.java new file mode 100644 index 00000000..d22eefb6 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/handler/GlobalExceptionHandler.java @@ -0,0 +1,136 @@ +package com.yanzhu.common.security.handler; + +import javax.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import com.yanzhu.common.core.constant.HttpStatus; +import com.yanzhu.common.core.exception.DemoModeException; +import com.yanzhu.common.core.exception.InnerAuthException; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.exception.auth.NotPermissionException; +import com.yanzhu.common.core.exception.auth.NotRoleException; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.domain.AjaxResult; + +/** + * 全局异常处理器 + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler +{ + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 权限码异常 + */ + @ExceptionHandler(NotPermissionException.class) + public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权"); + } + + /** + * 角色权限异常 + */ + @ExceptionHandler(NotRoleException.class) + public AjaxResult handleNotRoleException(NotRoleException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权"); + } + + /** + * 请求方式不支持 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); + return AjaxResult.error(e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) + { + log.error(e.getMessage(), e); + Integer code = e.getCode(); + return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); + } + + /** + * 拦截未知的运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult handleBindException(BindException e) + { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) + { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 内部认证异常 + */ + @ExceptionHandler(InnerAuthException.class) + public AjaxResult handleInnerAuthException(InnerAuthException e) + { + return AjaxResult.error(e.getMessage()); + } + + /** + * 演示模式异常 + */ + @ExceptionHandler(DemoModeException.class) + public AjaxResult handleDemoModeException(DemoModeException e) + { + return AjaxResult.error("演示模式,不允许操作"); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/interceptor/HeaderInterceptor.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/interceptor/HeaderInterceptor.java new file mode 100644 index 00000000..50d76026 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/interceptor/HeaderInterceptor.java @@ -0,0 +1,55 @@ +package com.yanzhu.common.security.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.yanzhu.common.security.auth.AuthUtil; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.AsyncHandlerInterceptor; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.context.SecurityContextHolder; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.model.LoginUser; + +/** + * 自定义请求头拦截器,将Header数据封装到线程变量中方便获取 + * 注意:此拦截器会同时验证当前用户有效期自动刷新有效期 + * + * @author ruoyi + */ +public class HeaderInterceptor implements AsyncHandlerInterceptor +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (!(handler instanceof HandlerMethod)) + { + return true; + } + + SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID)); + SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME)); + SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY)); + + String token = SecurityUtils.getToken(); + if (StringUtils.isNotEmpty(token)) + { + LoginUser loginUser = AuthUtil.getLoginUser(token); + if (StringUtils.isNotNull(loginUser)) + { + AuthUtil.verifyLoginUserExpire(loginUser); + SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); + } + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception + { + SecurityContextHolder.remove(); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/service/TokenService.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/service/TokenService.java new file mode 100644 index 00000000..aab600a2 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/service/TokenService.java @@ -0,0 +1,169 @@ +package com.yanzhu.common.security.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.stereotype.Component; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.utils.JwtUtils; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.ip.IpUtils; +import com.yanzhu.common.core.utils.uuid.IdUtils; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.model.LoginUser; + +/** + * token验证处理 + * + * @author ruoyi + */ +@Component +public class TokenService +{ + @Autowired + private RedisService redisService; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private final static long expireTime = CacheConstants.EXPIRATION; + + private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY; + + private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; + + /** + * 创建令牌 + */ + public Map createToken(LoginUser loginUser) + { + String token = IdUtils.fastUUID(); + Long userId = loginUser.getSysUser().getUserId(); + String userName = loginUser.getSysUser().getUserName(); + loginUser.setToken(token); + loginUser.setUserid(userId); + loginUser.setUsername(userName); + loginUser.setIpaddr(IpUtils.getIpAddr()); + refreshToken(loginUser); + + // Jwt存储信息 + Map claimsMap = new HashMap(); + claimsMap.put(SecurityConstants.USER_KEY, token); + claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); + claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); + + // 接口返回信息 + Map rspMap = new HashMap(); + rspMap.put("access_token", JwtUtils.createToken(claimsMap)); + rspMap.put("expires_in", expireTime); + return rspMap; + } + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser() + { + return getLoginUser(ServletUtils.getRequest()); + } + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(HttpServletRequest request) + { + // 获取请求携带的令牌 + String token = SecurityUtils.getToken(request); + return getLoginUser(token); + } + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(String token) + { + LoginUser user = null; + try + { + if (StringUtils.isNotEmpty(token)) + { + String userkey = JwtUtils.getUserKey(token); + user = redisService.getCacheObject(getTokenKey(userkey)); + return user; + } + } + catch (Exception e) + { + } + return user; + } + + /** + * 设置用户身份信息 + */ + 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 = JwtUtils.getUserKey(token); + redisService.deleteObject(getTokenKey(userkey)); + } + } + + /** + * 验证令牌有效期,相差不足120分钟,自动刷新缓存 + * + * @param loginUser + */ + 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()); + redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + } + + private String getTokenKey(String token) + { + return ACCESS_TOKEN + token; + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/DictUtils.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/DictUtils.java new file mode 100644 index 00000000..8e1fc0bb --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/DictUtils.java @@ -0,0 +1,75 @@ +package com.yanzhu.common.security.utils; + +import java.util.Collection; +import java.util.List; +import com.alibaba.fastjson2.JSONArray; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.system.api.domain.SysDictData; + +/** + * 字典工具类 + * + * @author ruoyi + */ +public class DictUtils +{ + /** + * 设置字典缓存 + * + * @param key 参数键 + * @param dictDatas 字典数据列表 + */ + public static void setDictCache(String key, List dictDatas) + { + SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas); + } + + /** + * 获取字典缓存 + * + * @param key 参数键 + * @return dictDatas 字典数据列表 + */ + public static List getDictCache(String key) + { + JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key)); + if (StringUtils.isNotNull(arrayCache)) + { + return arrayCache.toList(SysDictData.class); + } + return null; + } + + /** + * 删除指定字典缓存 + * + * @param key 字典键 + */ + public static void removeDictCache(String key) + { + SpringUtils.getBean(RedisService.class).deleteObject(getCacheKey(key)); + } + + /** + * 清空字典缓存 + */ + public static void clearDictCache() + { + Collection keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*"); + SpringUtils.getBean(RedisService.class).deleteObject(keys); + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + public static String getCacheKey(String configKey) + { + return CacheConstants.SYS_DICT_KEY + configKey; + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/SecurityUtils.java b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/SecurityUtils.java new file mode 100644 index 00000000..7faf4f46 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/java/com/yanzhu/common/security/utils/SecurityUtils.java @@ -0,0 +1,118 @@ +package com.yanzhu.common.security.utils; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.TokenConstants; +import com.yanzhu.common.core.context.SecurityContextHolder; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.system.api.model.LoginUser; + +/** + * 权限获取工具类 + * + * @author ruoyi + */ +public class SecurityUtils +{ + /** + * 获取用户ID + */ + public static Long getUserId() + { + return SecurityContextHolder.getUserId(); + } + + /** + * 获取用户名称 + */ + public static String getUsername() + { + return SecurityContextHolder.getUserName(); + } + + /** + * 获取用户key + */ + public static String getUserKey() + { + return SecurityContextHolder.getUserKey(); + } + + /** + * 获取登录用户信息 + */ + public static LoginUser getLoginUser() + { + return SecurityContextHolder.get(SecurityConstants.LOGIN_USER, LoginUser.class); + } + + /** + * 获取请求token + */ + public static String getToken() + { + return getToken(ServletUtils.getRequest()); + } + + /** + * 根据request获取请求token + */ + public static String getToken(HttpServletRequest request) + { + // 从header获取token标识 + String token = request.getHeader(TokenConstants.AUTHENTICATION); + return replaceTokenPrefix(token); + } + + /** + * 裁剪token前缀 + */ + public static String replaceTokenPrefix(String token) + { + // 如果前端设置了令牌前缀,则裁剪掉前缀 + if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) + { + token = token.replaceFirst(TokenConstants.PREFIX, ""); + } + return token; + } + + /** + * 是否为管理员 + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } + + /** + * 生成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); + } +} diff --git a/yanzhu-common/yanzhu-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..2812e335 --- /dev/null +++ b/yanzhu-common/yanzhu-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,5 @@ +com.yanzhu.common.security.config.WebMvcConfig +com.yanzhu.common.security.service.TokenService +com.yanzhu.common.security.aspect.PreAuthorizeAspect +com.yanzhu.common.security.aspect.InnerAuthAspect +com.yanzhu.common.security.handler.GlobalExceptionHandler diff --git a/yanzhu-common/yanzhu-common-swagger/pom.xml b/yanzhu-common/yanzhu-common-swagger/pom.xml new file mode 100644 index 00000000..b8aa9b90 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/pom.xml @@ -0,0 +1,34 @@ + + + + com.yanzhu + yanzhu-common + 3.6.2 + + 4.0.0 + + yanzhu-common-swagger + + + yanzhu-common-swagger系统接口 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + io.springfox + springfox-swagger2 + ${swagger.fox.version} + + + + diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/annotation/EnableCustomSwagger2.java b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/annotation/EnableCustomSwagger2.java new file mode 100644 index 00000000..e46e08d0 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/annotation/EnableCustomSwagger2.java @@ -0,0 +1,20 @@ +package com.yanzhu.common.swagger.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 org.springframework.context.annotation.Import; +import com.yanzhu.common.swagger.config.SwaggerAutoConfiguration; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import({ SwaggerAutoConfiguration.class }) +public @interface EnableCustomSwagger2 +{ + +} diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerAutoConfiguration.java b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerAutoConfiguration.java new file mode 100644 index 00000000..c8d3a449 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerAutoConfiguration.java @@ -0,0 +1,129 @@ +package com.yanzhu.common.swagger.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.ApiSelectorBuilder; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +@EnableAutoConfiguration +@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true) +public class SwaggerAutoConfiguration +{ + /** + * 默认的排除路径,排除Spring Boot默认的错误处理路径和端点 + */ + private static final List DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**"); + + private static final String BASE_PATH = "/**"; + + @Bean + @ConditionalOnMissingBean + public SwaggerProperties swaggerProperties() + { + return new SwaggerProperties(); + } + + @Bean + public Docket api(SwaggerProperties swaggerProperties) + { + // base-path处理 + if (swaggerProperties.getBasePath().isEmpty()) + { + swaggerProperties.getBasePath().add(BASE_PATH); + } + // noinspection unchecked + List> basePath = new ArrayList>(); + swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path))); + + // exclude-path处理 + if (swaggerProperties.getExcludePath().isEmpty()) + { + swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH); + } + + List> excludePath = new ArrayList<>(); + swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path))); + + ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2).host(swaggerProperties.getHost()) + .apiInfo(apiInfo(swaggerProperties)).select() + .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())); + + swaggerProperties.getBasePath().forEach(p -> builder.paths(PathSelectors.ant(p))); + swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate())); + + return builder.build().securitySchemes(securitySchemes()).securityContexts(securityContexts()).pathMapping("/"); + } + + /** + * 安全模式,这里指定token通过Authorization头请求头传递 + */ + private List securitySchemes() + { + List apiKeyList = new ArrayList(); + apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); + return apiKeyList; + } + + /** + * 安全上下文 + */ + private List securityContexts() + { + List securityContexts = new ArrayList<>(); + securityContexts.add( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .operationSelector(o -> o.requestMappingPattern().matches("/.*")) + .build()); + return securityContexts; + } + + /** + * 默认的全局鉴权策略 + * + * @return + */ + 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(SwaggerProperties swaggerProperties) + { + return new ApiInfoBuilder() + .title(swaggerProperties.getTitle()) + .description(swaggerProperties.getDescription()) + .license(swaggerProperties.getLicense()) + .licenseUrl(swaggerProperties.getLicenseUrl()) + .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) + .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail())) + .version(swaggerProperties.getVersion()) + .build(); + } +} diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerBeanPostProcessor.java b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerBeanPostProcessor.java new file mode 100644 index 00000000..429fd351 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerBeanPostProcessor.java @@ -0,0 +1,54 @@ +package com.yanzhu.common.swagger.config; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; +import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; +import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider; +import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; +import java.lang.reflect.Field; +import java.util.List; +import java.util.stream.Collectors; + +/** + * swagger 在 springboot 2.6.x 不兼容问题的处理 + * + * @author ruoyi + */ +@Component +public class SwaggerBeanPostProcessor implements BeanPostProcessor +{ + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException + { + if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) + { + customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); + } + return bean; + } + + private void customizeSpringfoxHandlerMappings(List mappings) + { + List copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null) + .collect(Collectors.toList()); + mappings.clear(); + mappings.addAll(copy); + } + + @SuppressWarnings("unchecked") + private List getHandlerMappings(Object bean) + { + try + { + Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); + field.setAccessible(true); + return (List) field.get(bean); + } + catch (IllegalArgumentException | IllegalAccessException e) + { + throw new IllegalStateException(e); + } + } +} diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerProperties.java b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerProperties.java new file mode 100644 index 00000000..189ba672 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerProperties.java @@ -0,0 +1,345 @@ +package com.yanzhu.common.swagger.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties("swagger") +public class SwaggerProperties +{ + /** + * 是否开启swagger + */ + private Boolean enabled; + + /** + * swagger会解析的包路径 + **/ + private String basePackage = ""; + + /** + * swagger会解析的url规则 + **/ + private List basePath = new ArrayList<>(); + + /** + * 在basePath基础上需要排除的url规则 + **/ + private List excludePath = new ArrayList<>(); + + /** + * 标题 + **/ + private String title = ""; + + /** + * 描述 + **/ + private String description = ""; + + /** + * 版本 + **/ + private String version = ""; + + /** + * 许可证 + **/ + private String license = ""; + + /** + * 许可证URL + **/ + private String licenseUrl = ""; + + /** + * 服务条款URL + **/ + private String termsOfServiceUrl = ""; + + /** + * host信息 + **/ + private String host = ""; + + /** + * 联系人信息 + */ + private Contact contact = new Contact(); + + /** + * 全局统一鉴权配置 + **/ + private Authorization authorization = new Authorization(); + + public Boolean getEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public String getBasePackage() + { + return basePackage; + } + + public void setBasePackage(String basePackage) + { + this.basePackage = basePackage; + } + + public List getBasePath() + { + return basePath; + } + + public void setBasePath(List basePath) + { + this.basePath = basePath; + } + + public List getExcludePath() + { + return excludePath; + } + + public void setExcludePath(List excludePath) + { + this.excludePath = excludePath; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getLicense() + { + return license; + } + + public void setLicense(String license) + { + this.license = license; + } + + public String getLicenseUrl() + { + return licenseUrl; + } + + public void setLicenseUrl(String licenseUrl) + { + this.licenseUrl = licenseUrl; + } + + public String getTermsOfServiceUrl() + { + return termsOfServiceUrl; + } + + public void setTermsOfServiceUrl(String termsOfServiceUrl) + { + this.termsOfServiceUrl = termsOfServiceUrl; + } + + public String getHost() + { + return host; + } + + public void setHost(String host) + { + this.host = host; + } + + public Contact getContact() + { + return contact; + } + + public void setContact(Contact contact) + { + this.contact = contact; + } + + public Authorization getAuthorization() + { + return authorization; + } + + public void setAuthorization(Authorization authorization) + { + this.authorization = authorization; + } + + public static class Contact + { + /** + * 联系人 + **/ + private String name = ""; + /** + * 联系人url + **/ + private String url = ""; + /** + * 联系人email + **/ + private String email = ""; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + } + + public static class Authorization + { + /** + * 鉴权策略ID,需要和SecurityReferences ID保持一致 + */ + private String name = ""; + + /** + * 需要开启鉴权URL的正则 + */ + private String authRegex = "^.*$"; + + /** + * 鉴权作用域列表 + */ + private List authorizationScopeList = new ArrayList<>(); + + private List tokenUrlList = new ArrayList<>(); + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getAuthRegex() + { + return authRegex; + } + + public void setAuthRegex(String authRegex) + { + this.authRegex = authRegex; + } + + public List getAuthorizationScopeList() + { + return authorizationScopeList; + } + + public void setAuthorizationScopeList(List authorizationScopeList) + { + this.authorizationScopeList = authorizationScopeList; + } + + public List getTokenUrlList() + { + return tokenUrlList; + } + + public void setTokenUrlList(List tokenUrlList) + { + this.tokenUrlList = tokenUrlList; + } + } + + public static class AuthorizationScope + { + /** + * 作用域名称 + */ + private String scope = ""; + + /** + * 作用域描述 + */ + private String description = ""; + + public String getScope() + { + return scope; + } + + public void setScope(String scope) + { + this.scope = scope; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerWebConfiguration.java b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerWebConfiguration.java new file mode 100644 index 00000000..de0dfa73 --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/java/com/yanzhu/common/swagger/config/SwaggerWebConfiguration.java @@ -0,0 +1,22 @@ +package com.yanzhu.common.swagger.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * swagger 资源映射路径 + * + * @author ruoyi + */ +@Configuration +public class SwaggerWebConfiguration implements WebMvcConfigurer +{ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** swagger-ui 地址 */ + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); + } +} \ No newline at end of file diff --git a/yanzhu-common/yanzhu-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yanzhu-common/yanzhu-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..405cbcaa --- /dev/null +++ b/yanzhu-common/yanzhu-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,3 @@ +com.yanzhu.common.swagger.config.SwaggerAutoConfiguration +com.yanzhu.common.swagger.config.SwaggerWebConfiguration +com.yanzhu.common.swagger.config.SwaggerBeanPostProcessor diff --git a/yanzhu-gateway/pom.xml b/yanzhu-gateway/pom.xml new file mode 100644 index 00000000..4ad099ff --- /dev/null +++ b/yanzhu-gateway/pom.xml @@ -0,0 +1,153 @@ + + + com.yanzhu + yanzhu + 3.6.2 + + 4.0.0 + + yanzhu-gateway + + + yanzhu-gateway网关模块 + + + + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + com.alibaba.cloud + spring-cloud-alibaba-sentinel-gateway + + + + + com.alibaba.csp + sentinel-datasource-nacos + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + org.springframework.cloud + spring-cloud-loadbalancer + + + + + pro.fessional + kaptcha + + + + + com.yanzhu + yanzhu-common-redis + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + io.springfox + springfox-swagger2 + ${swagger.fox.version} + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-two-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/RuoYiGatewayApplication.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/RuoYiGatewayApplication.java new file mode 100644 index 00000000..8a2778b2 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/RuoYiGatewayApplication.java @@ -0,0 +1,29 @@ +package com.yanzhu.gateway; + +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 RuoYiGatewayApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiGatewayApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/CaptchaConfig.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/CaptchaConfig.java new file mode 100644 index 00000000..5cccb777 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package com.yanzhu.gateway.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.yanzhu.gateway.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; + } +} \ No newline at end of file diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/GatewayConfig.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/GatewayConfig.java new file mode 100644 index 00000000..57818e6e --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/GatewayConfig.java @@ -0,0 +1,23 @@ +package com.yanzhu.gateway.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import com.yanzhu.gateway.handler.SentinelFallbackHandler; + +/** + * 网关限流配置 + * + * @author ruoyi + */ +@Configuration +public class GatewayConfig +{ + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SentinelFallbackHandler sentinelGatewayExceptionHandler() + { + return new SentinelFallbackHandler(); + } +} \ No newline at end of file diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/KaptchaTextCreator.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/KaptchaTextCreator.java new file mode 100644 index 00000000..9e5e1288 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/KaptchaTextCreator.java @@ -0,0 +1,75 @@ +package com.yanzhu.gateway.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 验证码文本生成器 + * + * @author ruoyi + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = random.nextInt(3); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if ((x != 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else if (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/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/RouterFunctionConfiguration.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/RouterFunctionConfiguration.java new file mode 100644 index 00000000..ef4692d9 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/RouterFunctionConfiguration.java @@ -0,0 +1,31 @@ +package com.yanzhu.gateway.config; + +import com.yanzhu.gateway.handler.ValidateCodeHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.RequestPredicates; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; + +/** + * 路由配置信息 + * + * @author ruoyi + */ +@Configuration +public class RouterFunctionConfiguration +{ + @Autowired + private ValidateCodeHandler validateCodeHandler; + + @SuppressWarnings("rawtypes") + @Bean + public RouterFunction routerFunction() + { + return RouterFunctions.route( + RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), + validateCodeHandler); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/SwaggerProvider.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/SwaggerProvider.java new file mode 100644 index 00000000..5400cec3 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/SwaggerProvider.java @@ -0,0 +1,79 @@ +package com.yanzhu.gateway.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.config.GatewayProperties; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.support.NameUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.config.ResourceHandlerRegistry; +import org.springframework.web.reactive.config.WebFluxConfigurer; +import springfox.documentation.swagger.web.SwaggerResource; +import springfox.documentation.swagger.web.SwaggerResourcesProvider; + +/** + * 聚合系统接口 + * + * @author ruoyi + */ +@Component +public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer +{ + /** + * Swagger2默认的url后缀 + */ + public static final String SWAGGER2URL = "/v2/api-docs"; + + /** + * 网关路由 + */ + @Lazy + @Autowired + private RouteLocator routeLocator; + + @Autowired + private GatewayProperties gatewayProperties; + + /** + * 聚合其他服务接口 + * + * @return + */ + @Override + public List get() + { + List resourceList = new ArrayList<>(); + List routes = new ArrayList<>(); + // 获取网关中配置的route + routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); + gatewayProperties.getRoutes().stream() + .filter(routeDefinition -> routes + .contains(routeDefinition.getId())) + .forEach(routeDefinition -> routeDefinition.getPredicates().stream() + .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName())) + .filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId())) + .forEach(predicateDefinition -> resourceList + .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs() + .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL))))); + return resourceList; + } + + private SwaggerResource swaggerResource(String name, String location) + { + SwaggerResource swaggerResource = new SwaggerResource(); + swaggerResource.setName(name); + swaggerResource.setLocation(location); + swaggerResource.setSwaggerVersion("2.0"); + return swaggerResource; + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** swagger-ui 地址 */ + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/CaptchaProperties.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/CaptchaProperties.java new file mode 100644 index 00000000..02121b1b --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/CaptchaProperties.java @@ -0,0 +1,46 @@ +package com.yanzhu.gateway.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 验证码配置 + * + * @author ruoyi + */ +@Configuration +@RefreshScope +@ConfigurationProperties(prefix = "security.captcha") +public class CaptchaProperties +{ + /** + * 验证码开关 + */ + private Boolean enabled; + + /** + * 验证码类型(math 数组计算 char 字符) + */ + private String type; + + public Boolean getEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/IgnoreWhiteProperties.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/IgnoreWhiteProperties.java new file mode 100644 index 00000000..413b3265 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/IgnoreWhiteProperties.java @@ -0,0 +1,33 @@ +package com.yanzhu.gateway.config.properties; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 放行白名单配置 + * + * @author ruoyi + */ +@Configuration +@RefreshScope +@ConfigurationProperties(prefix = "security.ignore") +public class IgnoreWhiteProperties +{ + /** + * 放行白名单配置,网关不校验此处的白名单 + */ + private List whites = new ArrayList<>(); + + public List getWhites() + { + return whites; + } + + public void setWhites(List whites) + { + this.whites = whites; + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/XssProperties.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/XssProperties.java new file mode 100644 index 00000000..7d0203c5 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/config/properties/XssProperties.java @@ -0,0 +1,48 @@ +package com.yanzhu.gateway.config.properties; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * XSS跨站脚本配置 + * + * @author ruoyi + */ +@Configuration +@RefreshScope +@ConfigurationProperties(prefix = "security.xss") +public class XssProperties +{ + /** + * Xss开关 + */ + private Boolean enabled; + + /** + * 排除路径 + */ + private List excludeUrls = new ArrayList<>(); + + public Boolean getEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public List getExcludeUrls() + { + return excludeUrls; + } + + public void setExcludeUrls(List excludeUrls) + { + this.excludeUrls = excludeUrls; + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/AuthFilter.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/AuthFilter.java new file mode 100644 index 00000000..e7ef385d --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/AuthFilter.java @@ -0,0 +1,135 @@ +package com.yanzhu.gateway.filter; + +import com.yanzhu.gateway.config.properties.IgnoreWhiteProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.HttpStatus; +import com.yanzhu.common.core.constant.SecurityConstants; +import com.yanzhu.common.core.constant.TokenConstants; +import com.yanzhu.common.core.utils.JwtUtils; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.redis.service.RedisService; +import io.jsonwebtoken.Claims; +import reactor.core.publisher.Mono; + +/** + * 网关鉴权 + * + * @author ruoyi + */ +@Component +public class AuthFilter implements GlobalFilter, Ordered +{ + private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); + + // 排除过滤的 uri 地址,nacos自行添加 + @Autowired + private IgnoreWhiteProperties ignoreWhite; + + @Autowired + private RedisService redisService; + + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) + { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpRequest.Builder mutate = request.mutate(); + + String url = request.getURI().getPath(); + // 跳过不需要验证的路径 + if (StringUtils.matches(url, ignoreWhite.getWhites())) + { + return chain.filter(exchange); + } + String token = getToken(request); + if (StringUtils.isEmpty(token)) + { + return unauthorizedResponse(exchange, "令牌不能为空"); + } + Claims claims = JwtUtils.parseToken(token); + if (claims == null) + { + return unauthorizedResponse(exchange, "令牌已过期或验证不正确!"); + } + String userkey = JwtUtils.getUserKey(claims); + boolean islogin = redisService.hasKey(getTokenKey(userkey)); + if (!islogin) + { + return unauthorizedResponse(exchange, "登录状态已过期"); + } + String userid = JwtUtils.getUserId(claims); + String username = JwtUtils.getUserName(claims); + if (StringUtils.isEmpty(userid)) + { + return unauthorizedResponse(exchange, "令牌验证失败"); + } + + // 设置用户信息到请求 + addHeader(mutate, SecurityConstants.USER_KEY, userkey); + addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); + addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); + // 内部请求来源参数清除 + removeHeader(mutate, SecurityConstants.FROM_SOURCE); + return chain.filter(exchange.mutate().request(mutate.build()).build()); + } + + private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) + { + if (value == null) + { + return; + } + String valueStr = value.toString(); + String valueEncode = ServletUtils.urlEncode(valueStr); + mutate.header(name, valueEncode); + } + + private void removeHeader(ServerHttpRequest.Builder mutate, String name) + { + mutate.headers(httpHeaders -> httpHeaders.remove(name)).build(); + } + + private Mono unauthorizedResponse(ServerWebExchange exchange, String msg) + { + log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); + } + + /** + * 获取缓存key + */ + private String getTokenKey(String token) + { + return CacheConstants.LOGIN_TOKEN_KEY + token; + } + + /** + * 获取请求token + */ + private String getToken(ServerHttpRequest request) + { + String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION); + // 如果前端设置了令牌前缀,则裁剪掉前缀 + if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) + { + token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY); + } + return token; + } + + @Override + public int getOrder() + { + return -200; + } +} \ No newline at end of file diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/BlackListUrlFilter.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/BlackListUrlFilter.java new file mode 100644 index 00000000..0365ad48 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/BlackListUrlFilter.java @@ -0,0 +1,65 @@ +package com.yanzhu.gateway.filter; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.utils.ServletUtils; + +/** + * 黑名单过滤器 + * + * @author ruoyi + */ +@Component +public class BlackListUrlFilter extends AbstractGatewayFilterFactory +{ + @Override + public GatewayFilter apply(Config config) + { + return (exchange, chain) -> { + + String url = exchange.getRequest().getURI().getPath(); + if (config.matchBlacklist(url)) + { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问"); + } + + return chain.filter(exchange); + }; + } + + public BlackListUrlFilter() + { + super(Config.class); + } + + public static class Config + { + private List blacklistUrl; + + private List blacklistUrlPattern = new ArrayList<>(); + + public boolean matchBlacklist(String url) + { + return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); + } + + public List getBlacklistUrl() + { + return blacklistUrl; + } + + public void setBlacklistUrl(List blacklistUrl) + { + this.blacklistUrl = blacklistUrl; + this.blacklistUrlPattern.clear(); + this.blacklistUrl.forEach(url -> { + this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); + }); + } + } + +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/CacheRequestFilter.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/CacheRequestFilter.java new file mode 100644 index 00000000..4066ee4a --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/CacheRequestFilter.java @@ -0,0 +1,87 @@ +package com.yanzhu.gateway.filter; + +import java.util.Collections; +import java.util.List; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * 获取body请求数据(解决流不能重复读取问题) + * + * @author ruoyi + */ +@Component +public class CacheRequestFilter extends AbstractGatewayFilterFactory +{ + public CacheRequestFilter() + { + super(Config.class); + } + + @Override + public String name() + { + return "CacheRequestFilter"; + } + + @Override + public GatewayFilter apply(Config config) + { + CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter(); + Integer order = config.getOrder(); + if (order == null) + { + return cacheRequestGatewayFilter; + } + return new OrderedGatewayFilter(cacheRequestGatewayFilter, order); + } + + public static class CacheRequestGatewayFilter implements GatewayFilter + { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) + { + // GET DELETE 不过滤 + HttpMethod method = exchange.getRequest().getMethod(); + if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) + { + return chain.filter(exchange); + } + return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> { + if (serverHttpRequest == exchange.getRequest()) + { + return chain.filter(exchange); + } + return chain.filter(exchange.mutate().request(serverHttpRequest).build()); + }); + } + } + + @Override + public List shortcutFieldOrder() + { + return Collections.singletonList("order"); + } + + static class Config + { + private Integer order; + + public Integer getOrder() + { + return order; + } + + public void setOrder(Integer order) + { + this.order = order; + } + } +} \ No newline at end of file diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/ValidateCodeFilter.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/ValidateCodeFilter.java new file mode 100644 index 00000000..cffed109 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/ValidateCodeFilter.java @@ -0,0 +1,79 @@ +package com.yanzhu.gateway.filter; + +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicReference; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.yanzhu.common.core.utils.ServletUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.gateway.config.properties.CaptchaProperties; +import com.yanzhu.gateway.service.ValidateCodeService; +import reactor.core.publisher.Flux; + +/** + * 验证码过滤器 + * + * @author ruoyi + */ +@Component +public class ValidateCodeFilter extends AbstractGatewayFilterFactory +{ + private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" }; + + @Autowired + private ValidateCodeService validateCodeService; + + @Autowired + private CaptchaProperties captchaProperties; + + private static final String CODE = "code"; + + private static final String UUID = "uuid"; + + @Override + public GatewayFilter apply(Object config) + { + return (exchange, chain) -> { + ServerHttpRequest request = exchange.getRequest(); + + // 非登录/注册请求或验证码关闭,不处理 + if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) + { + return chain.filter(exchange); + } + + try + { + String rspStr = resolveBodyFromRequest(request); + JSONObject obj = JSON.parseObject(rspStr); + validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); + } + catch (Exception e) + { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); + } + return chain.filter(exchange); + }; + } + + private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) + { + // 获取请求体 + Flux body = serverHttpRequest.getBody(); + AtomicReference bodyRef = new AtomicReference<>(); + body.subscribe(buffer -> { + CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); + DataBufferUtils.release(buffer); + bodyRef.set(charBuffer.toString()); + }); + return bodyRef.get(); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/XssFilter.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/XssFilter.java new file mode 100644 index 00000000..db5354d2 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/filter/XssFilter.java @@ -0,0 +1,129 @@ +package com.yanzhu.gateway.filter; + +import java.nio.charset.StandardCharsets; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.core.io.buffer.NettyDataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpRequestDecorator; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.html.EscapeUtil; +import com.yanzhu.gateway.config.properties.XssProperties; +import io.netty.buffer.ByteBufAllocator; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * 跨站脚本过滤器 + * + * @author ruoyi + */ +@Component +@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true") +public class XssFilter implements GlobalFilter, Ordered +{ + // 跨站脚本的 xss 配置,nacos自行添加 + @Autowired + private XssProperties xss; + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) + { + ServerHttpRequest request = exchange.getRequest(); + // xss开关未开启 或 通过nacos关闭,不过滤 + if (!xss.getEnabled()) + { + return chain.filter(exchange); + } + // GET DELETE 不过滤 + HttpMethod method = request.getMethod(); + if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) + { + return chain.filter(exchange); + } + // 非json类型,不过滤 + if (!isJsonRequest(exchange)) + { + return chain.filter(exchange); + } + // excludeUrls 不过滤 + String url = request.getURI().getPath(); + if (StringUtils.matches(url, xss.getExcludeUrls())) + { + return chain.filter(exchange); + } + ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); + return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); + + } + + private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) + { + ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) + { + @Override + public Flux getBody() + { + Flux body = super.getBody(); + return body.buffer().map(dataBuffers -> { + DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); + DataBuffer join = dataBufferFactory.join(dataBuffers); + byte[] content = new byte[join.readableByteCount()]; + join.read(content); + DataBufferUtils.release(join); + String bodyStr = new String(content, StandardCharsets.UTF_8); + // 防xss攻击过滤 + bodyStr = EscapeUtil.clean(bodyStr); + // 转成字节 + byte[] bytes = bodyStr.getBytes(); + NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); + DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); + return buffer; + }); + } + + @Override + public HttpHeaders getHeaders() + { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length + httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + return httpHeaders; + } + + }; + return serverHttpRequestDecorator; + } + + /** + * 是否是Json请求 + * + * @param exchange HTTP请求 + */ + public boolean isJsonRequest(ServerWebExchange exchange) + { + String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } + + @Override + public int getOrder() + { + return -100; + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/GatewayExceptionHandler.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/GatewayExceptionHandler.java new file mode 100644 index 00000000..9414062d --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/GatewayExceptionHandler.java @@ -0,0 +1,56 @@ +package com.yanzhu.gateway.handler; + +import org.springframework.cloud.gateway.support.NotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ResponseStatusException; +import org.springframework.web.server.ServerWebExchange; +import com.yanzhu.common.core.utils.ServletUtils; +import reactor.core.publisher.Mono; + +/** + * 网关统一异常处理 + * + * @author ruoyi + */ +@Order(-1) +@Configuration +public class GatewayExceptionHandler implements ErrorWebExceptionHandler +{ + private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); + + @Override + public Mono handle(ServerWebExchange exchange, Throwable ex) + { + ServerHttpResponse response = exchange.getResponse(); + + if (exchange.getResponse().isCommitted()) + { + return Mono.error(ex); + } + + String msg; + + if (ex instanceof NotFoundException) + { + msg = "服务未找到"; + } + else if (ex instanceof ResponseStatusException) + { + ResponseStatusException responseStatusException = (ResponseStatusException) ex; + msg = responseStatusException.getMessage(); + } + else + { + msg = "内部服务器错误"; + } + + log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); + + return ServletUtils.webFluxResponseWriter(response, msg); + } +} \ No newline at end of file diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SentinelFallbackHandler.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SentinelFallbackHandler.java new file mode 100644 index 00000000..2a7e59a2 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SentinelFallbackHandler.java @@ -0,0 +1,41 @@ +package com.yanzhu.gateway.handler; + +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.yanzhu.common.core.utils.ServletUtils; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebExceptionHandler; +import reactor.core.publisher.Mono; + +/** + * 自定义限流异常处理 + * + * @author ruoyi + */ +public class SentinelFallbackHandler implements WebExceptionHandler +{ + private Mono writeResponse(ServerResponse response, ServerWebExchange exchange) + { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试"); + } + + @Override + public Mono handle(ServerWebExchange exchange, Throwable ex) + { + if (exchange.getResponse().isCommitted()) + { + return Mono.error(ex); + } + if (!BlockException.isBlockException(ex)) + { + return Mono.error(ex); + } + return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); + } + + private Mono handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) + { + return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SwaggerHandler.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SwaggerHandler.java new file mode 100644 index 00000000..a3e82db8 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/SwaggerHandler.java @@ -0,0 +1,56 @@ +package com.yanzhu.gateway.handler; + +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; +import springfox.documentation.swagger.web.SecurityConfiguration; +import springfox.documentation.swagger.web.SecurityConfigurationBuilder; +import springfox.documentation.swagger.web.SwaggerResourcesProvider; +import springfox.documentation.swagger.web.UiConfiguration; +import springfox.documentation.swagger.web.UiConfigurationBuilder; + +@RestController +@RequestMapping("/swagger-resources") +public class SwaggerHandler +{ + @Autowired(required = false) + private SecurityConfiguration securityConfiguration; + + @Autowired(required = false) + private UiConfiguration uiConfiguration; + + private final SwaggerResourcesProvider swaggerResources; + + @Autowired + public SwaggerHandler(SwaggerResourcesProvider swaggerResources) + { + this.swaggerResources = swaggerResources; + } + + @GetMapping("/configuration/security") + public Mono> securityConfiguration() + { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), + HttpStatus.OK)); + } + + @GetMapping("/configuration/ui") + public Mono> uiConfiguration() + { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + + @SuppressWarnings("rawtypes") + @GetMapping("") + public Mono swaggerResources() + { + return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/ValidateCodeHandler.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/ValidateCodeHandler.java new file mode 100644 index 00000000..ae9e4374 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/handler/ValidateCodeHandler.java @@ -0,0 +1,42 @@ +package com.yanzhu.gateway.handler; + +import java.io.IOException; + +import com.yanzhu.gateway.service.ValidateCodeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.server.HandlerFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import com.yanzhu.common.core.exception.CaptchaException; +import com.yanzhu.common.core.web.domain.AjaxResult; +import reactor.core.publisher.Mono; + +/** + * 验证码获取 + * + * @author ruoyi + */ +@Component +public class ValidateCodeHandler implements HandlerFunction +{ + @Autowired + private ValidateCodeService validateCodeService; + + @Override + public Mono handle(ServerRequest serverRequest) + { + AjaxResult ajax; + try + { + ajax = validateCodeService.createCaptcha(); + } + catch (CaptchaException | IOException e) + { + return Mono.error(e); + } + return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)); + } +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/ValidateCodeService.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/ValidateCodeService.java new file mode 100644 index 00000000..a1cc027e --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/ValidateCodeService.java @@ -0,0 +1,23 @@ +package com.yanzhu.gateway.service; + +import java.io.IOException; +import com.yanzhu.common.core.exception.CaptchaException; +import com.yanzhu.common.core.web.domain.AjaxResult; + +/** + * 验证码处理 + * + * @author ruoyi + */ +public interface ValidateCodeService +{ + /** + * 生成验证码 + */ + public AjaxResult createCaptcha() throws IOException, CaptchaException; + + /** + * 校验验证码 + */ + public void checkCaptcha(String key, String value) throws CaptchaException; +} diff --git a/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/impl/ValidateCodeServiceImpl.java b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/impl/ValidateCodeServiceImpl.java new file mode 100644 index 00000000..5404ae28 --- /dev/null +++ b/yanzhu-gateway/src/main/java/com/yanzhu/gateway/service/impl/ValidateCodeServiceImpl.java @@ -0,0 +1,119 @@ +package com.yanzhu.gateway.service.impl; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.FastByteArrayOutputStream; +import com.google.code.kaptcha.Producer; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.exception.CaptchaException; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.sign.Base64; +import com.yanzhu.common.core.utils.uuid.IdUtils; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.gateway.config.properties.CaptchaProperties; +import com.yanzhu.gateway.service.ValidateCodeService; + +/** + * 验证码实现处理 + * + * @author ruoyi + */ +@Service +public class ValidateCodeServiceImpl implements ValidateCodeService +{ + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + + @Autowired + private RedisService redisService; + + @Autowired + private CaptchaProperties captchaProperties; + + /** + * 生成验证码 + */ + @Override + public AjaxResult createCaptcha() throws IOException, CaptchaException + { + AjaxResult ajax = AjaxResult.success(); + boolean captchaEnabled = captchaProperties.getEnabled(); + ajax.put("captchaEnabled", captchaEnabled); + if (!captchaEnabled) + { + return ajax; + } + + // 保存验证码信息 + String uuid = IdUtils.simpleUUID(); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + String captchaType = captchaProperties.getType(); + // 生成验证码 + 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); + } + + redisService.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; + } + + /** + * 校验验证码 + */ + @Override + public void checkCaptcha(String code, String uuid) throws CaptchaException + { + if (StringUtils.isEmpty(code)) + { + throw new CaptchaException("验证码不能为空"); + } + if (StringUtils.isEmpty(uuid)) + { + throw new CaptchaException("验证码已失效"); + } + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + String captcha = redisService.getCacheObject(verifyKey); + redisService.deleteObject(verifyKey); + + if (!code.equalsIgnoreCase(captcha)) + { + throw new CaptchaException("验证码错误"); + } + } +} diff --git a/yanzhu-gateway/src/main/resources/banner.txt b/yanzhu-gateway/src/main/resources/banner.txt new file mode 100644 index 00000000..ceced29f --- /dev/null +++ b/yanzhu-gateway/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ + (_) | | + _ __ _ _ ___ _ _ _ ______ __ _ __ _ | |_ ___ __ __ __ _ _ _ +| '__|| | | | / _ \ | | | || ||______| / _` | / _` || __| / _ \\ \ /\ / / / _` || | | | +| | | |_| || (_) || |_| || | | (_| || (_| || |_ | __/ \ V V / | (_| || |_| | +|_| \__,_| \___/ \__, ||_| \__, | \__,_| \__| \___| \_/\_/ \__,_| \__, | + __/ | __/ | __/ | + |___/ |___/ |___/ \ No newline at end of file diff --git a/yanzhu-gateway/src/main/resources/bootstrap.yml b/yanzhu-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..e5fe0ad3 --- /dev/null +++ b/yanzhu-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,40 @@ +# Tomcat +server: + port: 8080 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-gateway + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + sentinel: + # 取消控制台懒加载 + eager: true + transport: + # 控制台地址 + dashboard: 62.234.3.186:8718 + # nacos配置持久化 + datasource: + ds1: + nacos: + server-addr: @discovery.server-addr@ + dataId: sentinel-ruoyi-gateway + groupId: DEFAULT_GROUP + data-type: json + rule-type: gw-flow diff --git a/yanzhu-gateway/src/main/resources/logback.xml b/yanzhu-gateway/src/main/resources/logback.xml new file mode 100644 index 00000000..9867bb7b --- /dev/null +++ b/yanzhu-gateway/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/pom.xml b/yanzhu-modules/pom.xml new file mode 100644 index 00000000..20037b42 --- /dev/null +++ b/yanzhu-modules/pom.xml @@ -0,0 +1,27 @@ + + + + com.yanzhu + yanzhu + 3.6.2 + + 4.0.0 + + + yanzhu-system + yanzhu-gen + yanzhu-job + yanzhu-file + yanzhu-manage + yanzhu-wechat + + + yanzhu-modules + pom + + + yanzhu-modules业务模块 + + + diff --git a/yanzhu-modules/yanzhu-file/pom.xml b/yanzhu-modules/yanzhu-file/pom.xml new file mode 100644 index 00000000..2f249789 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/pom.xml @@ -0,0 +1,131 @@ + + + + com.yanzhu + yanzhu-modules + 3.6.2 + + 4.0.0 + + yanzhu-modules-file + + + yanzhu-modules-file文件服务 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.github.tobato + fastdfs-client + + + + + io.minio + minio + ${minio.version} + + + + + com.yanzhu + yanzhu-api-system + + + + + com.yanzhu + yanzhu-common-swagger + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/RuoYiFileApplication.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/RuoYiFileApplication.java new file mode 100644 index 00000000..3122ab20 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/RuoYiFileApplication.java @@ -0,0 +1,31 @@ +package com.yanzhu.file; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 文件服务 + * + * @author ruoyi + */ +@EnableCustomSwagger2 +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) +public class RuoYiFileApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiFileApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/MinioConfig.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/MinioConfig.java new file mode 100644 index 00000000..2a808f66 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/MinioConfig.java @@ -0,0 +1,82 @@ +package com.yanzhu.file.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import io.minio.MinioClient; + +/** + * Minio 配置信息 + * + * @author ruoyi + */ +@Configuration +@ConfigurationProperties(prefix = "minio") +public class MinioConfig +{ + /** + * 服务地址 + */ + private String url; + + /** + * 用户名 + */ + private String accessKey; + + /** + * 密码 + */ + private String secretKey; + + /** + * 存储桶名称 + */ + private String bucketName; + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + public String getAccessKey() + { + return accessKey; + } + + public void setAccessKey(String accessKey) + { + this.accessKey = accessKey; + } + + public String getSecretKey() + { + return secretKey; + } + + public void setSecretKey(String secretKey) + { + this.secretKey = secretKey; + } + + public String getBucketName() + { + return bucketName; + } + + public void setBucketName(String bucketName) + { + this.bucketName = bucketName; + } + + @Bean + public MinioClient getMinioClient() + { + return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); + } +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/ResourcesConfig.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/ResourcesConfig.java new file mode 100644 index 00000000..7e9db660 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/config/ResourcesConfig.java @@ -0,0 +1,50 @@ +package com.yanzhu.file.config; + +import java.io.File; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 通用映射配置 + * + * @author ruoyi + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer +{ + /** + * 上传文件存储在本地的根路径 + */ + @Value("${file.path}") + private String localFilePath; + + /** + * 资源映射路径 前缀 + */ + @Value("${file.prefix}") + public String localFilePrefix; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(localFilePrefix + "/**") + .addResourceLocations("file:" + localFilePath + File.separator); + } + + /** + * 开启跨域 + */ + @Override + public void addCorsMappings(CorsRegistry registry) { + // 设置允许跨域的路由 + registry.addMapping(localFilePrefix + "/**") + // 设置允许跨域请求的域名 + .allowedOrigins("*") + // 设置允许的方法 + .allowedMethods("GET"); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/controller/SysFileController.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/controller/SysFileController.java new file mode 100644 index 00000000..9c42bfbe --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/controller/SysFileController.java @@ -0,0 +1,48 @@ +package com.yanzhu.file.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.utils.file.FileUtils; +import com.yanzhu.file.service.ISysFileService; +import com.yanzhu.system.api.domain.SysFile; + +/** + * 文件请求处理 + * + * @author ruoyi + */ +@RestController +public class SysFileController +{ + private static final Logger log = LoggerFactory.getLogger(SysFileController.class); + + @Autowired + private ISysFileService sysFileService; + + /** + * 文件上传请求 + */ + @PostMapping("upload") + public R upload(MultipartFile file) + { + try + { + // 上传并返回访问地址 + String url = sysFileService.uploadFile(file); + SysFile sysFile = new SysFile(); + sysFile.setName(FileUtils.getName(url)); + sysFile.setUrl(url); + return R.ok(sysFile); + } + catch (Exception e) + { + log.error("上传文件失败", e); + return R.fail(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/FastDfsSysFileServiceImpl.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/FastDfsSysFileServiceImpl.java new file mode 100644 index 00000000..9dcdca9d --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/FastDfsSysFileServiceImpl.java @@ -0,0 +1,42 @@ +package com.yanzhu.file.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import com.github.tobato.fastdfs.domain.fdfs.StorePath; +import com.github.tobato.fastdfs.service.FastFileStorageClient; +import com.yanzhu.common.core.utils.file.FileTypeUtils; + +/** + * FastDFS 文件存储 + * + * @author ruoyi + */ +@Service +public class FastDfsSysFileServiceImpl implements ISysFileService +{ + /** + * 域名或本机访问地址 + */ + @Value("${fdfs.domain}") + public String domain; + + @Autowired + private FastFileStorageClient storageClient; + + /** + * FastDfs文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), + FileTypeUtils.getExtension(file), null); + return domain + "/" + storePath.getFullPath(); + } +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/ISysFileService.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/ISysFileService.java new file mode 100644 index 00000000..b30dc4f1 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/ISysFileService.java @@ -0,0 +1,20 @@ +package com.yanzhu.file.service; + +import org.springframework.web.multipart.MultipartFile; + +/** + * 文件上传接口 + * + * @author ruoyi + */ +public interface ISysFileService +{ + /** + * 文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + public String uploadFile(MultipartFile file) throws Exception; +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/LocalSysFileServiceImpl.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/LocalSysFileServiceImpl.java new file mode 100644 index 00000000..535407bb --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/LocalSysFileServiceImpl.java @@ -0,0 +1,50 @@ +package com.yanzhu.file.service; + +import com.yanzhu.file.utils.FileUploadUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +/** + * 本地文件存储 + * + * @author ruoyi + */ +@Primary +@Service +public class LocalSysFileServiceImpl implements ISysFileService +{ + /** + * 资源映射路径 前缀 + */ + @Value("${file.prefix}") + public String localFilePrefix; + + /** + * 域名或本机访问地址 + */ + @Value("${file.domain}") + public String domain; + + /** + * 上传文件存储在本地的根路径 + */ + @Value("${file.path}") + private String localFilePath; + + /** + * 本地文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + String name = FileUploadUtils.upload(localFilePath, file); + String url = domain + localFilePrefix + name; + return url; + } +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/MinioSysFileServiceImpl.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/MinioSysFileServiceImpl.java new file mode 100644 index 00000000..a2a2ff35 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/service/MinioSysFileServiceImpl.java @@ -0,0 +1,45 @@ +package com.yanzhu.file.service; + +import com.yanzhu.file.config.MinioConfig; +import com.yanzhu.file.utils.FileUploadUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import io.minio.MinioClient; +import io.minio.PutObjectArgs; + +/** + * Minio 文件存储 + * + * @author ruoyi + */ +@Service +public class MinioSysFileServiceImpl implements ISysFileService +{ + @Autowired + private MinioConfig minioConfig; + + @Autowired + private MinioClient client; + + /** + * 本地文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + String fileName = FileUploadUtils.extractFilename(file); + PutObjectArgs args = PutObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .stream(file.getInputStream(), file.getSize(), -1) + .contentType(file.getContentType()) + .build(); + client.putObject(args); + return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; + } +} diff --git a/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/utils/FileUploadUtils.java b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/utils/FileUploadUtils.java new file mode 100644 index 00000000..742ac23e --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/java/com/yanzhu/file/utils/FileUploadUtils.java @@ -0,0 +1,180 @@ +package com.yanzhu.file.utils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Objects; +import org.apache.commons.io.FilenameUtils; +import org.springframework.web.multipart.MultipartFile; +import com.yanzhu.common.core.exception.file.FileNameLengthLimitExceededException; +import com.yanzhu.common.core.exception.file.FileSizeLimitExceededException; +import com.yanzhu.common.core.exception.file.InvalidExtensionException; +import com.yanzhu.common.core.utils.DateUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.file.FileTypeUtils; +import com.yanzhu.common.core.utils.file.MimeTypeUtils; +import com.yanzhu.common.core.utils.uuid.Seq; + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileUploadUtils +{ + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException + { + try + { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param allowedExtension 上传文件类型 + * @return 返回上传成功的文件名 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws FileNameLengthLimitExceededException 文件名太长 + * @throws IOException 比如读写文件出错时 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, + InvalidExtensionException + { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + assertAllowed(file, allowedExtension); + + String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(fileName); + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) + { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), FileTypeUtils.getExtension(file)); + } + + private 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.isAbsolute() ? desc : desc.getAbsoluteFile(); + } + + private static final String getPathFileName(String fileName) throws IOException + { + String pathFileName = "/" + fileName; + return pathFileName; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (size > DEFAULT_MAX_SIZE) + { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = FileTypeUtils.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 true/false + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) + { + for (String str : allowedExtension) + { + if (str.equalsIgnoreCase(extension)) + { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-file/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-file/src/main/resources/banner.txt new file mode 100644 index 00000000..27cacb9c --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ __ _ _ + (_) / _|(_)| | + _ __ _ _ ___ _ _ _ ______ | |_ _ | | ___ +| '__|| | | | / _ \ | | | || ||______|| _|| || | / _ \ +| | | |_| || (_) || |_| || | | | | || || __/ +|_| \__,_| \___/ \__, ||_| |_| |_||_| \___| + __/ | + |___/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-file/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-file/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..bdadcd56 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9300 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-file + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-file/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-file/src/main/resources/logback.xml new file mode 100644 index 00000000..294eccc3 --- /dev/null +++ b/yanzhu-modules/yanzhu-file/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/pom.xml b/yanzhu-modules/yanzhu-gen/pom.xml new file mode 100644 index 00000000..c1ebe0e0 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/pom.xml @@ -0,0 +1,137 @@ + + + + com.yanzhu + yanzhu-modules + 3.6.2 + + 4.0.0 + + yanzhu-modules-gen + + + yanzhu-modules-gen代码生成 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + org.apache.velocity + velocity-engine-core + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/RuoYiGenApplication.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/RuoYiGenApplication.java new file mode 100644 index 00000000..6b6fa9aa --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/RuoYiGenApplication.java @@ -0,0 +1,34 @@ +package com.yanzhu.gen; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 代码生成 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class RuoYiGenApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiGenApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/config/GenConfig.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/config/GenConfig.java new file mode 100644 index 00000000..3ec03c1b --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/config/GenConfig.java @@ -0,0 +1,66 @@ +package com.yanzhu.gen.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 代码生成相关配置 + * + * @author ruoyi + */ +@Component +@ConfigurationProperties(prefix = "gen") +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; + } + + public void setAuthor(String author) + { + GenConfig.author = author; + } + + public static String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + GenConfig.packageName = packageName; + } + + public static boolean getAutoRemovePre() + { + return autoRemovePre; + } + + public void setAutoRemovePre(boolean autoRemovePre) + { + GenConfig.autoRemovePre = autoRemovePre; + } + + public static String getTablePrefix() + { + return tablePrefix; + } + + public void setTablePrefix(String tablePrefix) + { + GenConfig.tablePrefix = tablePrefix; + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/controller/GenController.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/controller/GenController.java new file mode 100644 index 00000000..87198bc3 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/controller/GenController.java @@ -0,0 +1,212 @@ +package com.yanzhu.gen.controller; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletResponse; + +import com.yanzhu.gen.domain.GenTableColumn; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.gen.domain.GenTable; +import com.yanzhu.gen.service.IGenTableColumnService; +import com.yanzhu.gen.service.IGenTableService; + +/** + * 代码生成 操作处理 + * + * @author ruoyi + */ +@RequestMapping("/gen") +@RestController +public class GenController extends BaseController +{ + @Autowired + private IGenTableService genTableService; + + @Autowired + private IGenTableColumnService genTableColumnService; + + /** + * 查询代码生成列表 + */ + @RequiresPermissions("tool:gen:list") + @GetMapping("/list") + public TableDataInfo genList(GenTable genTable) + { + startPage(); + List list = genTableService.selectGenTableList(genTable); + return getDataTable(list); + } + + /** + * 修改代码生成业务 + */ + @RequiresPermissions("tool:gen:query") + @GetMapping(value = "/{tableId}") + public AjaxResult getInfo(@PathVariable Long tableId) + { + GenTable table = genTableService.selectGenTableById(tableId); + List tables = genTableService.selectGenTableAll(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + Map map = new HashMap(); + map.put("info", table); + map.put("rows", list); + map.put("tables", tables); + return success(map); + } + + /** + * 查询数据库列表 + */ + @RequiresPermissions("tool:gen:list") + @GetMapping("/db/list") + public TableDataInfo dataList(GenTable genTable) + { + startPage(); + List list = genTableService.selectDbTableList(genTable); + return getDataTable(list); + } + + /** + * 查询数据表字段列表 + */ + @GetMapping(value = "/column/{tableId}") + public TableDataInfo columnList(Long tableId) + { + TableDataInfo dataInfo = new TableDataInfo(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + dataInfo.setRows(list); + dataInfo.setTotal(list.size()); + return dataInfo; + } + + /** + * 导入表结构(保存) + */ + @RequiresPermissions("tool:gen:import") + @Log(title = "代码生成", businessType = BusinessType.IMPORT) + @PostMapping("/importTable") + public AjaxResult importTableSave(String tables) + { + String[] tableNames = Convert.toStrArray(tables); + // 查询表信息 + List tableList = genTableService.selectDbTableListByNames(tableNames); + genTableService.importGenTable(tableList); + return success(); + } + + /** + * 修改保存代码生成业务 + */ + @RequiresPermissions("tool:gen:edit") + @Log(title = "代码生成", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult editSave(@Validated @RequestBody GenTable genTable) + { + genTableService.validateEdit(genTable); + genTableService.updateGenTable(genTable); + return success(); + } + + /** + * 删除代码生成 + */ + @RequiresPermissions("tool:gen:remove") + @Log(title = "代码生成", businessType = BusinessType.DELETE) + @DeleteMapping("/{tableIds}") + public AjaxResult remove(@PathVariable Long[] tableIds) + { + genTableService.deleteGenTableByIds(tableIds); + return success(); + } + + /** + * 预览代码 + */ + @RequiresPermissions("tool:gen:preview") + @GetMapping("/preview/{tableId}") + public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException + { + Map dataMap = genTableService.previewCode(tableId); + return success(dataMap); + } + + /** + * 生成代码(下载方式) + */ + @RequiresPermissions("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); + } + + /** + * 生成代码(自定义路径) + */ + @RequiresPermissions("tool:gen:code") + @Log(title = "代码生成", businessType = BusinessType.GENCODE) + @GetMapping("/genCode/{tableName}") + public AjaxResult genCode(@PathVariable("tableName") String tableName) + { + genTableService.generatorCode(tableName); + return success(); + } + + /** + * 同步数据库 + */ + @RequiresPermissions("tool:gen:edit") + @Log(title = "代码生成", businessType = BusinessType.UPDATE) + @GetMapping("/synchDb/{tableName}") + public AjaxResult synchDb(@PathVariable("tableName") String tableName) + { + genTableService.synchDb(tableName); + return success(); + } + + /** + * 批量生成代码 + */ + @RequiresPermissions("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.setHeader("Content-Disposition", "attachment; filename=\"yanzhu.zip\""); + response.addHeader("Content-Length", "" + data.length); + response.setContentType("application/octet-stream; charset=UTF-8"); + IOUtils.write(data, response.getOutputStream()); + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTable.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTable.java new file mode 100644 index 00000000..fe3c76d3 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTable.java @@ -0,0 +1,370 @@ +package com.yanzhu.gen.domain; + +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.apache.commons.lang3.ArrayUtils; +import com.yanzhu.common.core.constant.GenConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 业务表 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); + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTableColumn.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTableColumn.java new file mode 100644 index 00000000..717c014a --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/domain/GenTableColumn.java @@ -0,0 +1,374 @@ +package com.yanzhu.gen.domain; + +import javax.validation.constraints.NotBlank; + +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 代码生成业务字段表 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; + } + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableColumnMapper.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableColumnMapper.java new file mode 100644 index 00000000..4e570eb6 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableColumnMapper.java @@ -0,0 +1,60 @@ +package com.yanzhu.gen.mapper; + +import java.util.List; +import com.yanzhu.gen.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); +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableMapper.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableMapper.java new file mode 100644 index 00000000..957d84e7 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/mapper/GenTableMapper.java @@ -0,0 +1,83 @@ +package com.yanzhu.gen.mapper; + +import java.util.List; +import com.yanzhu.gen.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); +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableColumnServiceImpl.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableColumnServiceImpl.java new file mode 100644 index 00000000..c19646e0 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableColumnServiceImpl.java @@ -0,0 +1,69 @@ +package com.yanzhu.gen.service; + +import java.util.List; + +import com.yanzhu.gen.domain.GenTableColumn; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.gen.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)); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableServiceImpl.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableServiceImpl.java new file mode 100644 index 00000000..c8944b39 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/GenTableServiceImpl.java @@ -0,0 +1,522 @@ +package com.yanzhu.gen.service; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import com.yanzhu.gen.domain.GenTableColumn; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.constant.GenConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.text.CharsetKit; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.gen.domain.GenTable; +import com.yanzhu.gen.mapper.GenTableColumnMapper; +import com.yanzhu.gen.mapper.GenTableMapper; +import com.yanzhu.gen.util.GenUtils; +import com.yanzhu.gen.util.VelocityInitializer; +import com.yanzhu.gen.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(rollbackFor = Exception.class) + 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(rollbackFor = Exception.class) + public void deleteGenTableByIds(Long[] tableIds) + { + genTableMapper.deleteGenTableByIds(tableIds); + genTableColumnMapper.deleteGenTableColumnByIds(tableIds); + } + + /** + * 导入表结构 + * + * @param tableList 导入表列表 + */ + @Override + @Transactional(rollbackFor = Exception.class) + 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(rollbackFor = Exception.class) + public void synchDb(String tableName) + { + GenTable table = genTableMapper.selectGenTableByName(tableName); + List tableColumns = table.getColumns(); + Map tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity())); + + List dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); + if (StringUtils.isEmpty(dbTableColumns)) + { + throw new ServiceException("同步数据失败,原表结构不存在"); + } + List dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); + + dbTableColumns.forEach(column -> { + GenUtils.initColumnField(column, table); + if (tableColumnMap.containsKey(column.getColumnName())) + { + GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName()); + column.setColumnId(prevColumn.getColumnId()); + if (column.isList()) + { + // 如果是列表,继续保留查询方式/字典类型选项 + column.setDictType(prevColumn.getDictType()); + column.setQueryType(prevColumn.getQueryType()); + } + if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk() + && (column.isInsert() || column.isEdit()) + && ((column.isUsableColumn()) || (!column.isSuperColumn()))) + { + // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项 + column.setIsRequired(prevColumn.getIsRequired()); + column.setHtmlType(prevColumn.getHtmlType()); + } + genTableColumnMapper.updateGenTableColumn(column); + } + else + { + genTableColumnMapper.insertGenTableColumn(column); + } + }); + + List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); + if (StringUtils.isNotEmpty(delColumns)) + { + genTableColumnMapper.deleteGenTableColumns(delColumns); + } + } + + /** + * 批量生成代码(下载方式) + * + * @param tableNames 表数组 + * @return 数据 + */ + @Override + public byte[] downloadCode(String[] tableNames) + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + for (String tableName : tableNames) + { + generatorCode(tableName, zip); + } + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + /** + * 查询表信息并生成代码 + */ + private void generatorCode(String tableName, ZipOutputStream zip) + { + // 查询表信息 + GenTable table = genTableMapper.selectGenTableByName(tableName); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模板列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + try + { + // 添加到zip + zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); + IOUtils.write(sw.toString(), zip, Constants.UTF8); + IOUtils.closeQuietly(sw); + zip.flush(); + zip.closeEntry(); + } + catch (IOException e) + { + log.error("渲染模板失败,表名:" + table.getTableName(), e); + } + } + } + + /** + * 修改保存参数校验 + * + * @param genTable 业务信息 + */ + @Override + public void validateEdit(GenTable genTable) + { + if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) + { + String options = JSON.toJSONString(genTable.getParams()); + JSONObject paramsObj = JSON.parseObject(options); + if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) + { + throw new ServiceException("树编码字段不能为空"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) + { + throw new ServiceException("树父编码字段不能为空"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) + { + throw new ServiceException("树名称字段不能为空"); + } + else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) + { + if (StringUtils.isEmpty(genTable.getSubTableName())) + { + throw new ServiceException("关联子表的表名不能为空"); + } + else if (StringUtils.isEmpty(genTable.getSubTableFkName())) + { + throw new ServiceException("子表关联的外键名不能为空"); + } + } + } + } + + /** + * 设置主键列信息 + * + * @param table 业务表信息 + */ + public void setPkColumn(GenTable table) + { + for (GenTableColumn column : table.getColumns()) + { + if (column.isPk()) + { + table.setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getPkColumn())) + { + table.setPkColumn(table.getColumns().get(0)); + } + if (GenConstants.TPL_SUB.equals(table.getTplCategory())) + { + for (GenTableColumn column : table.getSubTable().getColumns()) + { + if (column.isPk()) + { + table.getSubTable().setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getSubTable().getPkColumn())) + { + table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0)); + } + } + } + + /** + * 设置主子表信息 + * + * @param table 业务表信息 + */ + public void setSubTable(GenTable table) + { + String subTableName = table.getSubTableName(); + if (StringUtils.isNotEmpty(subTableName)) + { + table.setSubTable(genTableMapper.selectGenTableByName(subTableName)); + } + } + + /** + * 设置代码生成其他选项值 + * + * @param genTable 设置后的生成对象 + */ + public void setTableFromOptions(GenTable genTable) + { + JSONObject paramsObj = JSON.parseObject(genTable.getOptions()); + if (StringUtils.isNotNull(paramsObj)) + { + String treeCode = paramsObj.getString(GenConstants.TREE_CODE); + String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID); + String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME); + + genTable.setTreeCode(treeCode); + genTable.setTreeParentCode(treeParentCode); + genTable.setTreeName(treeName); + genTable.setParentMenuId(parentMenuId); + genTable.setParentMenuName(parentMenuName); + } + } + + /** + * 获取代码生成地址 + * + * @param table 业务表信息 + * @param template 模板文件路径 + * @return 生成地址 + */ + public static String getGenPath(GenTable table, String template) + { + String genPath = table.getGenPath(); + if (StringUtils.equals(genPath, "/")) + { + return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table); + } + return genPath + File.separator + VelocityUtils.getFileName(template, table); + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableColumnService.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableColumnService.java new file mode 100644 index 00000000..9ddd91b5 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableColumnService.java @@ -0,0 +1,44 @@ +package com.yanzhu.gen.service; + +import java.util.List; +import com.yanzhu.gen.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/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableService.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableService.java new file mode 100644 index 00000000..5b976024 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/service/IGenTableService.java @@ -0,0 +1,121 @@ +package com.yanzhu.gen.service; + +import java.util.List; +import java.util.Map; +import com.yanzhu.gen.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/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/GenUtils.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/GenUtils.java new file mode 100644 index 00000000..464275f4 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/GenUtils.java @@ -0,0 +1,258 @@ +package com.yanzhu.gen.util; + +import java.util.Arrays; + +import com.yanzhu.gen.config.GenConfig; +import com.yanzhu.gen.domain.GenTable; +import com.yanzhu.gen.domain.GenTableColumn; +import org.apache.commons.lang3.RegExUtils; +import com.yanzhu.common.core.constant.GenConstants; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 代码生成器 工具类 + * + * @author ruoyi + */ +public class GenUtils +{ + /** + * 初始化表信息 + */ + public static void initTable(GenTable genTable, String operName) + { + genTable.setClassName(convertClassName(genTable.getTableName())); + genTable.setPackageName(GenConfig.getPackageName()); + genTable.setModuleName(getModuleName(GenConfig.getPackageName())); + genTable.setBusinessName(getBusinessName(genTable.getTableName())); + genTable.setFunctionName(replaceText(genTable.getTableComment())); + genTable.setFunctionAuthor(GenConfig.getAuthor()); + genTable.setCreateBy(operName); + } + + /** + * 初始化列属性字段 + */ + public static void initColumnField(GenTableColumn column, GenTable table) + { + String dataType = getDbType(column.getColumnType()); + String columnName = column.getColumnName(); + column.setTableId(table.getTableId()); + column.setCreateBy(table.getCreateBy()); + // 设置java字段名 + column.setJavaField(StringUtils.toCamelCase(columnName)); + // 设置默认类型 + column.setJavaType(GenConstants.TYPE_STRING); + column.setQueryType(GenConstants.QUERY_EQ); + + if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) + { + // 字符串长度超过500设置为文本域 + Integer columnLength = getColumnLength(column.getColumnType()); + String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; + column.setHtmlType(htmlType); + } + else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) + { + column.setJavaType(GenConstants.TYPE_DATE); + column.setHtmlType(GenConstants.HTML_DATETIME); + } + else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) + { + column.setHtmlType(GenConstants.HTML_INPUT); + + // 如果是浮点型 统一用BigDecimal + String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); + if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) + { + column.setJavaType(GenConstants.TYPE_BIGDECIMAL); + } + // 如果是整形 + else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) + { + column.setJavaType(GenConstants.TYPE_INTEGER); + } + // 长整形 + else + { + column.setJavaType(GenConstants.TYPE_LONG); + } + } + + // 插入字段(默认所有字段都需要插入) + column.setIsInsert(GenConstants.REQUIRE); + + // 编辑字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) + { + column.setIsEdit(GenConstants.REQUIRE); + } + // 列表字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) + { + column.setIsList(GenConstants.REQUIRE); + } + // 查询字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) + { + column.setIsQuery(GenConstants.REQUIRE); + } + + // 查询字段类型 + if (StringUtils.endsWithIgnoreCase(columnName, "name")) + { + column.setQueryType(GenConstants.QUERY_LIKE); + } + // 状态字段设置单选框 + if (StringUtils.endsWithIgnoreCase(columnName, "status")) + { + column.setHtmlType(GenConstants.HTML_RADIO); + } + // 类型&性别字段设置下拉框 + else if (StringUtils.endsWithIgnoreCase(columnName, "type") + || StringUtils.endsWithIgnoreCase(columnName, "sex")) + { + column.setHtmlType(GenConstants.HTML_SELECT); + } + // 图片字段设置图片上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "image")) + { + column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD); + } + // 文件字段设置文件上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "file")) + { + column.setHtmlType(GenConstants.HTML_FILE_UPLOAD); + } + // 内容字段设置富文本控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "content")) + { + column.setHtmlType(GenConstants.HTML_EDITOR); + } + } + + /** + * 校验数组是否包含指定值 + * + * @param arr 数组 + * @param targetValue 值 + * @return 是否包含 + */ + public static boolean arraysContains(String[] arr, String targetValue) + { + return Arrays.asList(arr).contains(targetValue); + } + + /** + * 获取模块名 + * + * @param packageName 包名 + * @return 模块名 + */ + public static String getModuleName(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + int nameLength = packageName.length(); + return StringUtils.substring(packageName, lastIndex + 1, nameLength); + } + + /** + * 获取业务名 + * + * @param tableName 表名 + * @return 业务名 + */ + public static String getBusinessName(String tableName) + { + int lastIndex = tableName.lastIndexOf("_"); + int nameLength = tableName.length(); + return StringUtils.substring(tableName, lastIndex + 1, nameLength); + } + + /** + * 表名转换成Java类名 + * + * @param tableName 表名称 + * @return 类名 + */ + public static String convertClassName(String tableName) + { + boolean autoRemovePre = GenConfig.getAutoRemovePre(); + String tablePrefix = GenConfig.getTablePrefix(); + if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) + { + String[] searchList = StringUtils.split(tablePrefix, ","); + tableName = replaceFirst(tableName, searchList); + } + return StringUtils.convertToCamelCase(tableName); + } + + /** + * 批量替换前缀 + * + * @param replacementm 替换值 + * @param searchList 替换列表 + * @return + */ + public static String replaceFirst(String replacementm, String[] searchList) + { + String text = replacementm; + for (String searchString : searchList) + { + if (replacementm.startsWith(searchString)) + { + text = replacementm.replaceFirst(searchString, ""); + break; + } + } + return text; + } + + /** + * 关键字替换 + * + * @param text 需要被替换的名字 + * @return 替换后的名字 + */ + public static String replaceText(String text) + { + return RegExUtils.replaceAll(text, "(?:表|若依)", ""); + } + + /** + * 获取数据库类型字段 + * + * @param columnType 列类型 + * @return 截取后的列类型 + */ + public static String getDbType(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + return StringUtils.substringBefore(columnType, "("); + } + else + { + return columnType; + } + } + + /** + * 获取字段长度 + * + * @param columnType 列类型 + * @return 截取后的列类型 + */ + public static Integer getColumnLength(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + String length = StringUtils.substringBetween(columnType, "(", ")"); + return Integer.valueOf(length); + } + else + { + return 0; + } + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityInitializer.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityInitializer.java new file mode 100644 index 00000000..dab16d5f --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityInitializer.java @@ -0,0 +1,34 @@ +package com.yanzhu.gen.util; + +import java.util.Properties; +import org.apache.velocity.app.Velocity; +import com.yanzhu.common.core.constant.Constants; + +/** + * VelocityEngine工厂 + * + * @author ruoyi + */ +public class VelocityInitializer +{ + /** + * 初始化vm方法 + */ + public static void initVelocity() + { + Properties p = new Properties(); + try + { + // 加载classpath目录下的vm文件 + p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + // 定义字符集 + p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); + // 初始化Velocity引擎,指定配置Properties + Velocity.init(p); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityUtils.java b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityUtils.java new file mode 100644 index 00000000..b310ccc2 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/java/com/yanzhu/gen/util/VelocityUtils.java @@ -0,0 +1,403 @@ +package com.yanzhu.gen.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.yanzhu.gen.domain.GenTable; +import com.yanzhu.gen.domain.GenTableColumn; +import org.apache.velocity.VelocityContext; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.yanzhu.common.core.constant.GenConstants; +import com.yanzhu.common.core.utils.DateUtils; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 模板工具类 + * + * @author ruoyi + */ +public class VelocityUtils +{ + /** 项目空间路径 */ + private static final String PROJECT_PATH = "main/java"; + + /** mybatis空间路径 */ + private static final String MYBATIS_PATH = "main/resources/mapper"; + + /** 默认上级菜单,系统工具 */ + private static final String DEFAULT_PARENT_MENU_ID = "3"; + + /** + * 设置模板变量信息 + * + * @return 模板列表 + */ + public static VelocityContext prepareContext(GenTable genTable) + { + String moduleName = genTable.getModuleName(); + String businessName = genTable.getBusinessName(); + String packageName = genTable.getPackageName(); + String tplCategory = genTable.getTplCategory(); + String functionName = genTable.getFunctionName(); + + VelocityContext velocityContext = new VelocityContext(); + velocityContext.put("tplCategory", genTable.getTplCategory()); + velocityContext.put("tableName", genTable.getTableName()); + velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】"); + velocityContext.put("ClassName", genTable.getClassName()); + velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName())); + velocityContext.put("moduleName", genTable.getModuleName()); + velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName())); + velocityContext.put("businessName", genTable.getBusinessName()); + velocityContext.put("basePackage", getPackagePrefix(packageName)); + velocityContext.put("packageName", packageName); + velocityContext.put("author", genTable.getFunctionAuthor()); + velocityContext.put("datetime", DateUtils.getDate()); + velocityContext.put("pkColumn", genTable.getPkColumn()); + velocityContext.put("importList", getImportList(genTable)); + velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); + velocityContext.put("columns", genTable.getColumns()); + velocityContext.put("table", genTable); + velocityContext.put("dicts", getDicts(genTable)); + setMenuVelocityContext(velocityContext, genTable); + if (GenConstants.TPL_TREE.equals(tplCategory)) + { + setTreeVelocityContext(velocityContext, genTable); + } + if (GenConstants.TPL_SUB.equals(tplCategory)) + { + setSubVelocityContext(velocityContext, genTable); + } + return velocityContext; + } + + public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String parentMenuId = getParentMenuId(paramsObj); + context.put("parentMenuId", parentMenuId); + } + + public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeCode = getTreecode(paramsObj); + String treeParentCode = getTreeParentCode(paramsObj); + String treeName = getTreeName(paramsObj); + + context.put("treeCode", treeCode); + context.put("treeParentCode", treeParentCode); + context.put("treeName", treeName); + context.put("expandColumn", getExpandColumn(genTable)); + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME)); + } + } + + public static void setSubVelocityContext(VelocityContext context, GenTable genTable) + { + GenTable subTable = genTable.getSubTable(); + String subTableName = genTable.getSubTableName(); + String subTableFkName = genTable.getSubTableFkName(); + String subClassName = genTable.getSubTable().getClassName(); + String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName); + + context.put("subTable", subTable); + context.put("subTableName", subTableName); + context.put("subTableFkName", subTableFkName); + context.put("subTableFkClassName", subTableFkClassName); + context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName)); + context.put("subClassName", subClassName); + context.put("subclassName", StringUtils.uncapitalize(subClassName)); + context.put("subImportList", getImportList(genTable.getSubTable())); + } + + /** + * 获取模板信息 + * + * @return 模板列表 + */ + public static List getTemplateList(String tplCategory) + { + List templates = new ArrayList(); + templates.add("vm/java/domain.java.vm"); + templates.add("vm/java/mapper.java.vm"); + templates.add("vm/java/service.java.vm"); + templates.add("vm/java/serviceImpl.java.vm"); + templates.add("vm/java/controller.java.vm"); + templates.add("vm/xml/mapper.xml.vm"); + templates.add("vm/sql/sql.vm"); + templates.add("vm/js/api.js.vm"); + if (GenConstants.TPL_CRUD.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + } + else if (GenConstants.TPL_TREE.equals(tplCategory)) + { + templates.add("vm/vue/index-tree.vue.vm"); + } + else if (GenConstants.TPL_SUB.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + templates.add("vm/java/sub-domain.java.vm"); + } + return templates; + } + + /** + * 获取文件名 + */ + public static String getFileName(String template, GenTable genTable) + { + // 文件名称 + String fileName = ""; + // 包路径 + String packageName = genTable.getPackageName(); + // 模块名 + String moduleName = genTable.getModuleName(); + // 大写类名 + String className = genTable.getClassName(); + // 业务名称 + String businessName = genTable.getBusinessName(); + + String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/"); + String mybatisPath = MYBATIS_PATH + "/" + moduleName; + String vuePath = "vue"; + + if (template.contains("domain.java.vm")) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, className); + } + if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory())) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName()); + } + else if (template.contains("mapper.java.vm")) + { + fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); + } + else if (template.contains("service.java.vm")) + { + fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className); + } + else if (template.contains("serviceImpl.java.vm")) + { + fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); + } + else if (template.contains("controller.java.vm")) + { + fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); + } + else if (template.contains("mapper.xml.vm")) + { + fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); + } + else if (template.contains("sql.vm")) + { + fileName = businessName + "Menu.sql"; + } + else if (template.contains("api.js.vm")) + { + fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName); + } + else if (template.contains("index.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + else if (template.contains("index-tree.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + return fileName; + } + + /** + * 获取包前缀 + * + * @param packageName 包名称 + * @return 包前缀名称 + */ + public static String getPackagePrefix(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + return StringUtils.substring(packageName, 0, lastIndex); + } + + /** + * 根据列类型获取导入包 + * + * @param genTable 业务表对象 + * @return 返回需要导入的包列表 + */ + public static HashSet getImportList(GenTable genTable) + { + List columns = genTable.getColumns(); + GenTable subGenTable = genTable.getSubTable(); + HashSet importList = new HashSet(); + if (StringUtils.isNotNull(subGenTable)) + { + importList.add("java.util.List"); + } + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) + { + importList.add("java.util.Date"); + importList.add("com.fasterxml.jackson.annotation.JsonFormat"); + } + else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) + { + importList.add("java.math.BigDecimal"); + } + } + return importList; + } + + /** + * 根据列类型获取字典组 + * + * @param genTable 业务表对象 + * @return 返回字典组 + */ + public static String getDicts(GenTable genTable) + { + List columns = genTable.getColumns(); + Set dicts = new HashSet(); + addDicts(dicts, columns); + if (StringUtils.isNotNull(genTable.getSubTable())) + { + List subColumns = genTable.getSubTable().getColumns(); + addDicts(dicts, subColumns); + } + return StringUtils.join(dicts, ", "); + } + + /** + * 添加字典列表 + * + * @param dicts 字典列表 + * @param columns 列集合 + */ + public static void addDicts(Set dicts, List columns) + { + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny( + column.getHtmlType(), + new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) + { + dicts.add("'" + column.getDictType() + "'"); + } + } + } + + /** + * 获取权限前缀 + * + * @param moduleName 模块名称 + * @param businessName 业务名称 + * @return 返回权限前缀 + */ + public static String getPermissionPrefix(String moduleName, String businessName) + { + return StringUtils.format("{}:{}", moduleName, businessName); + } + + /** + * 获取上级菜单ID字段 + * + * @param paramsObj 生成其他选项 + * @return 上级菜单ID字段 + */ + public static String getParentMenuId(JSONObject paramsObj) + { + if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID) + && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) + { + return paramsObj.getString(GenConstants.PARENT_MENU_ID); + } + return DEFAULT_PARENT_MENU_ID; + } + + /** + * 获取树编码 + * + * @param paramsObj 生成其他选项 + * @return 树编码 + */ + public static String getTreecode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树父编码 + * + * @param paramsObj 生成其他选项 + * @return 树父编码 + */ + public static String getTreeParentCode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树名称 + * + * @param paramsObj 生成其他选项 + * @return 树名称 + */ + public static String getTreeName(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); + } + return StringUtils.EMPTY; + } + + /** + * 获取需要在哪一列上面显示展开按钮 + * + * @param genTable 业务表对象 + * @return 展开按钮列序号 + */ + public static int getExpandColumn(GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + int num = 0; + for (GenTableColumn column : genTable.getColumns()) + { + if (column.isList()) + { + num++; + String columnName = column.getColumnName(); + if (columnName.equals(treeName)) + { + break; + } + } + } + return num; + } +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-gen/src/main/resources/banner.txt new file mode 100644 index 00000000..05f528cc --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ + (_) + _ __ _ _ ___ _ _ _ ______ __ _ ___ _ __ +| '__|| | | | / _ \ | | | || ||______| / _` | / _ \| '_ \ +| | | |_| || (_) || |_| || | | (_| || __/| | | | +|_| \__,_| \___/ \__, ||_| \__, | \___||_| |_| + __/ | __/ | + |___/ |___/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-gen/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..ea170bfd --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9202 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-gen + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-gen/src/main/resources/logback.xml new file mode 100644 index 00000000..ec8cfeba --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableColumnMapper.xml new file mode 100644 index 00000000..36a8af29 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/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/yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableMapper.xml b/yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableMapper.xml new file mode 100644 index 00000000..f73011cb --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/mapper/generator/GenTableMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table + + + + + + + + + + + + + + + + + + insert into gen_table ( + table_name, + table_comment, + class_name, + tpl_category, + package_name, + module_name, + business_name, + function_name, + function_author, + gen_type, + gen_path, + remark, + create_by, + create_time + )values( + #{tableName}, + #{tableComment}, + #{className}, + #{tplCategory}, + #{packageName}, + #{moduleName}, + #{businessName}, + #{functionName}, + #{functionAuthor}, + #{genType}, + #{genPath}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update gen_table + + table_name = #{tableName}, + table_comment = #{tableComment}, + sub_table_name = #{subTableName}, + sub_table_fk_name = #{subTableFkName}, + class_name = #{className}, + function_author = #{functionAuthor}, + gen_type = #{genType}, + gen_path = #{genPath}, + tpl_category = #{tplCategory}, + package_name = #{packageName}, + module_name = #{moduleName}, + business_name = #{businessName}, + function_name = #{functionName}, + options = #{options}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where table_id = #{tableId} + + + + delete from gen_table where table_id in + + #{tableId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/controller.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/controller.java.vm new file mode 100644 index 00000000..caab9bca --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/controller.java.vm @@ -0,0 +1,116 @@ +package ${packageName}.controller; + +import java.util.List; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +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 Log; +import BusinessType; +import RequiresPermissions; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; +import BaseController; +import AjaxResult; +import ExcelUtil; +#if($table.crud || $table.sub) +import TableDataInfo; +#elseif($table.tree) +#end + +/** + * ${functionName}Controller + * + * @author ${author} + * @date ${datetime} + */ +@RestController +@RequestMapping("/${businessName}") +public class ${ClassName}Controller extends BaseController +{ + @Autowired + private I${ClassName}Service ${className}Service; + + /** + * 查询${functionName}列表 + */ + @RequiresPermissions("${permissionPrefix}:list") + @GetMapping("/list") +#if($table.crud || $table.sub) + public TableDataInfo list(${ClassName} ${className}) + { + startPage(); + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + return getDataTable(list); + } +#elseif($table.tree) + public AjaxResult list(${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + return success(list); + } +#end + + /** + * 导出${functionName}列表 + */ + @RequiresPermissions("${permissionPrefix}:export") + @Log(title = "${functionName}", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, ${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); + ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); + util.exportExcel(response, list, "${functionName}数据"); + } + + /** + * 获取${functionName}详细信息 + */ + @RequiresPermissions("${permissionPrefix}:query") + @GetMapping(value = "/{${pkColumn.javaField}}") + public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) + { + return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField})); + } + + /** + * 新增${functionName} + */ + @RequiresPermissions("${permissionPrefix}:add") + @Log(title = "${functionName}", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.insert${ClassName}(${className})); + } + + /** + * 修改${functionName} + */ + @RequiresPermissions("${permissionPrefix}:edit") + @Log(title = "${functionName}", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.update${ClassName}(${className})); + } + + /** + * 删除${functionName} + */ + @RequiresPermissions("${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/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/domain.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/domain.java.vm new file mode 100644 index 00000000..006d657e --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/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 Excel; +#if($table.crud || $table.sub) +import BaseEntity; +#elseif($table.tree) +import 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/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/mapper.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/mapper.java.vm new file mode 100644 index 00000000..7e7d7c26 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/mapper.java.vm @@ -0,0 +1,91 @@ +package ${packageName}.mapper; + +import java.util.List; +import ${packageName}.domain.${ClassName}; +#if($table.sub) +import ${packageName}.domain.${subClassName}; +#end + +/** + * ${functionName}Mapper接口 + * + * @author ${author} + * @date ${datetime} + */ +public interface ${ClassName}Mapper +{ + /** + * 查询${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 查询${functionName}列表 + * + * @param ${className} ${functionName} + * @return ${functionName}集合 + */ + public List<${ClassName}> select${ClassName}List(${ClassName} ${className}); + + /** + * 新增${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int insert${ClassName}(${ClassName} ${className}); + + /** + * 修改${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ + public int update${ClassName}(${ClassName} ${className}); + + /** + * 删除${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 批量删除${functionName} + * + * @param ${pkColumn.javaField}s 需要删除的数据主键集合 + * @return 结果 + */ + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); +#if($table.sub) + + /** + * 批量删除${subTable.functionName} + * + * @param ${pkColumn.javaField}s 需要删除的数据主键集合 + * @return 结果 + */ + public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); + + /** + * 批量新增${subTable.functionName} + * + * @param ${subclassName}List ${subTable.functionName}列表 + * @return 结果 + */ + public int batch${subClassName}(List<${subClassName}> ${subclassName}List); + + + /** + * 通过${functionName}主键删除${subTable.functionName}信息 + * + * @param ${pkColumn.javaField} ${functionName}ID + * @return 结果 + */ + public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField}); +#end +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/service.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/service.java.vm new file mode 100644 index 00000000..264882b2 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/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/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/serviceImpl.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/serviceImpl.java.vm new file mode 100644 index 00000000..40d2dcf7 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/serviceImpl.java.vm @@ -0,0 +1,169 @@ +package ${packageName}.service.impl; + +import java.util.List; +#foreach ($column in $columns) +#if($column.javaField == 'createTime' || $column.javaField == 'updateTime') +import DateUtils; +#break +#end +#end +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +#if($table.sub) +import java.util.ArrayList; +import StringUtils; +import org.springframework.transaction.annotation.Transactional; +import ${packageName}.domain.${subClassName}; +#end +import ${packageName}.mapper.${ClassName}Mapper; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; + +/** + * ${functionName}Service业务层处理 + * + * @author ${author} + * @date ${datetime} + */ +@Service +public class ${ClassName}ServiceImpl implements I${ClassName}Service +{ + @Autowired + private ${ClassName}Mapper ${className}Mapper; + + /** + * 查询${functionName} + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + @Override + public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) + { + return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}); + } + + /** + * 查询${functionName}列表 + * + * @param ${className} ${functionName} + * @return ${functionName} + */ + @Override + public List<${ClassName}> select${ClassName}List(${ClassName} ${className}) + { + return ${className}Mapper.select${ClassName}List(${className}); + } + + /** + * 新增${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int insert${ClassName}(${ClassName} ${className}) + { +#foreach ($column in $columns) +#if($column.javaField == 'createTime') + ${className}.setCreateTime(DateUtils.getNowDate()); +#end +#end +#if($table.sub) + int rows = ${className}Mapper.insert${ClassName}(${className}); + insert${subClassName}(${className}); + return rows; +#else + return ${className}Mapper.insert${ClassName}(${className}); +#end + } + + /** + * 修改${functionName} + * + * @param ${className} ${functionName} + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int update${ClassName}(${ClassName} ${className}) + { +#foreach ($column in $columns) +#if($column.javaField == 'updateTime') + ${className}.setUpdateTime(DateUtils.getNowDate()); +#end +#end +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}()); + insert${subClassName}(${className}); +#end + return ${className}Mapper.update${ClassName}(${className}); + } + + /** + * 批量删除${functionName} + * + * @param ${pkColumn.javaField}s 需要删除的${functionName}主键 + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s) + { +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s); +#end + return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s); + } + + /** + * 删除${functionName}信息 + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ +#if($table.sub) + @Transactional +#end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) + { +#if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField}); +#end + return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}); + } +#if($table.sub) + + /** + * 新增${subTable.functionName}信息 + * + * @param ${className} ${functionName}对象 + */ + public void insert${subClassName}(${ClassName} ${className}) + { + List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List(); + ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}(); + if (StringUtils.isNotNull(${subclassName}List)) + { + List<${subClassName}> list = new ArrayList<${subClassName}>(); + for (${subClassName} ${subclassName} : ${subclassName}List) + { + ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField}); + list.add(${subclassName}); + } + if (list.size() > 0) + { + ${className}Mapper.batch${subClassName}(list); + } + } + } +#end +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/sub-domain.java.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/java/sub-domain.java.vm new file mode 100644 index 00000000..457056e4 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/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 Excel; +import 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/yanzhu-modules/yanzhu-gen/src/main/resources/vm/js/api.js.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/js/api.js.vm new file mode 100644 index 00000000..9295524a --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/js/api.js.vm @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询${functionName}列表 +export function list${BusinessName}(query) { + return request({ + url: '/${moduleName}/${businessName}/list', + method: 'get', + params: query + }) +} + +// 查询${functionName}详细 +export function get${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'get' + }) +} + +// 新增${functionName} +export function add${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'post', + data: data + }) +} + +// 修改${functionName} +export function update${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'put', + data: data + }) +} + +// 删除${functionName} +export function del${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'delete' + }) +} diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/sql/sql.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/sql/sql.vm new file mode 100644 index 00000000..05755835 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/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/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index-tree.vue.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index-tree.vue.vm new file mode 100644 index 00000000..7bbd2fc5 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index-tree.vue.vm @@ -0,0 +1,474 @@ + + + diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index.vue.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index.vue.vm new file mode 100644 index 00000000..8b25665a --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/index.vue.vm @@ -0,0 +1,590 @@ + + + diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm new file mode 100644 index 00000000..7bbd2fc5 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -0,0 +1,474 @@ + + + diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index.vue.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index.vue.vm new file mode 100644 index 00000000..8b25665a --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/index.vue.vm @@ -0,0 +1,590 @@ + + + diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/readme.txt b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/readme.txt new file mode 100644 index 00000000..10362d62 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/vue/v3/readme.txt @@ -0,0 +1 @@ +ʹõRuoYi-Cloud-Vue3ǰˣôҪһ´Ŀ¼ģindex.vue.vmindex-tree.vue.vmļϼvueĿ¼ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-gen/src/main/resources/vm/xml/mapper.xml.vm b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/xml/mapper.xml.vm new file mode 100644 index 00000000..0ceb3d85 --- /dev/null +++ b/yanzhu-modules/yanzhu-gen/src/main/resources/vm/xml/mapper.xml.vm @@ -0,0 +1,135 @@ + + + + + +#foreach ($column in $columns) + +#end + +#if($table.sub) + + + + + + +#foreach ($column in $subTable.columns) + +#end + +#end + + + select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName} + + + + + + + + insert into ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + $column.columnName, +#end +#end + + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + #{$column.javaField}, +#end +#end + + + + + update ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName) + $column.columnName = #{$column.javaField}, +#end +#end + + where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} in + + #{${pkColumn.javaField}} + + +#if($table.sub) + + + delete from ${subTableName} where ${subTableFkName} in + + #{${subTableFkclassName}} + + + + + delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}} + + + + insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values + + (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end) + + +#end + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/pom.xml b/yanzhu-modules/yanzhu-job/pom.xml new file mode 100644 index 00000000..022781d9 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/pom.xml @@ -0,0 +1,143 @@ + + + + com.yanzhu + yanzhu-modules + 3.6.2 + + 4.0.0 + + yanzhu-modules-job + + + yanzhu-modules-job定时任务 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + org.quartz-scheduler + quartz + + + com.mchange + c3p0 + + + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-two-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/RuoYiJobApplication.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/RuoYiJobApplication.java new file mode 100644 index 00000000..999b78cc --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/RuoYiJobApplication.java @@ -0,0 +1,34 @@ +package com.yanzhu.job; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 定时任务 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class RuoYiJobApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiJobApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 定时任务模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/config/ScheduleConfig.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/config/ScheduleConfig.java new file mode 100644 index 00000000..dc840c87 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/config/ScheduleConfig.java @@ -0,0 +1,57 @@ +//package com.yanzhu.job.config; +// +//import java.util.Properties; +//import javax.sql.DataSource; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.scheduling.quartz.SchedulerFactoryBean; +// +///** +// * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效) +// * +// * @author ruoyi +// */ +//@Configuration +//public class ScheduleConfig +//{ +// @Bean +// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) +// { +// SchedulerFactoryBean factory = new SchedulerFactoryBean(); +// factory.setDataSource(dataSource); +// +// // quartz参数 +// Properties prop = new Properties(); +// prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); +// prop.put("org.quartz.scheduler.instanceId", "AUTO"); +// // 线程池配置 +// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); +// prop.put("org.quartz.threadPool.threadCount", "20"); +// prop.put("org.quartz.threadPool.threadPriority", "5"); +// // JobStore配置 +// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); +// // 集群配置 +// prop.put("org.quartz.jobStore.isClustered", "true"); +// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); +// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); +// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); +// +// // sqlserver 启用 +// // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); +// prop.put("org.quartz.jobStore.misfireThreshold", "12000"); +// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); +// factory.setQuartzProperties(prop); +// +// factory.setSchedulerName("RuoyiScheduler"); +// // 延时启动 +// factory.setStartupDelay(1); +// factory.setApplicationContextSchedulerContextKey("applicationContextKey"); +// // 可选,QuartzScheduler +// // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 +// factory.setOverwriteExistingJobs(true); +// // 设置自动启动,默认为true +// factory.setAutoStartup(true); +// +// return factory; +// } +//} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobController.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobController.java new file mode 100644 index 00000000..3b8e7596 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobController.java @@ -0,0 +1,186 @@ +package com.yanzhu.job.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.exception.job.TaskException; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.job.domain.SysJob; +import com.yanzhu.job.service.ISysJobService; +import com.yanzhu.job.util.CronUtils; +import com.yanzhu.job.util.ScheduleUtils; + +/** + * 调度任务信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/job") +public class SysJobController extends BaseController +{ + @Autowired + private ISysJobService jobService; + + /** + * 查询定时任务列表 + */ + @RequiresPermissions("monitor:job:list") + @GetMapping("/list") + public TableDataInfo list(SysJob sysJob) + { + startPage(); + List list = jobService.selectJobList(sysJob); + return getDataTable(list); + } + + /** + * 导出定时任务列表 + */ + @RequiresPermissions("monitor:job:export") + @Log(title = "定时任务", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJob sysJob) + { + List list = jobService.selectJobList(sysJob); + ExcelUtil util = new ExcelUtil(SysJob.class); + util.exportExcel(response, list, "定时任务"); + } + + /** + * 获取定时任务详细信息 + */ + @RequiresPermissions("monitor:job:query") + @GetMapping(value = "/{jobId}") + public AjaxResult getInfo(@PathVariable("jobId") Long jobId) + { + return success(jobService.selectJobById(jobId)); + } + + /** + * 新增定时任务 + */ + @RequiresPermissions("monitor:job:add") + @Log(title = "定时任务", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); + } + job.setCreateBy(SecurityUtils.getUsername()); + return toAjax(jobService.insertJob(job)); + } + + /** + * 修改定时任务 + */ + @RequiresPermissions("monitor:job:edit") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); + } + job.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(jobService.updateJob(job)); + } + + /** + * 定时任务状态修改 + */ + @RequiresPermissions("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)); + } + + /** + * 定时任务立即执行一次 + */ + @RequiresPermissions("monitor:job:changeStatus") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/run") + public AjaxResult run(@RequestBody SysJob job) throws SchedulerException + { + boolean result = jobService.run(job); + return result ? success() : error("任务不存在或已过期!"); + } + + /** + * 删除定时任务 + */ + @RequiresPermissions("monitor:job:remove") + @Log(title = "定时任务", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobIds}") + public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException + { + jobService.deleteJobByIds(jobIds); + return success(); + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobLogController.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobLogController.java new file mode 100644 index 00000000..93cd7c85 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/controller/SysJobLogController.java @@ -0,0 +1,92 @@ +package com.yanzhu.job.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.yanzhu.job.domain.SysJobLog; +import com.yanzhu.job.service.ISysJobLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; + +/** + * 调度日志操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/job/log") +public class SysJobLogController extends BaseController +{ + @Autowired + private ISysJobLogService jobLogService; + + /** + * 查询定时任务调度日志列表 + */ + @RequiresPermissions("monitor:job:list") + @GetMapping("/list") + public TableDataInfo list(SysJobLog sysJobLog) + { + startPage(); + List list = jobLogService.selectJobLogList(sysJobLog); + return getDataTable(list); + } + + /** + * 导出定时任务调度日志列表 + */ + @RequiresPermissions("monitor:job:export") + @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJobLog sysJobLog) + { + List list = jobLogService.selectJobLogList(sysJobLog); + ExcelUtil util = new ExcelUtil(SysJobLog.class); + util.exportExcel(response, list, "调度日志"); + } + + /** + * 根据调度编号获取详细信息 + */ + @RequiresPermissions("monitor:job:query") + @GetMapping(value = "/{jobLogId}") + public AjaxResult getInfo(@PathVariable Long jobLogId) + { + return success(jobLogService.selectJobLogById(jobLogId)); + } + + /** + * 删除定时任务调度日志 + */ + @RequiresPermissions("monitor:job:remove") + @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobLogIds}") + public AjaxResult remove(@PathVariable Long[] jobLogIds) + { + return toAjax(jobLogService.deleteJobLogByIds(jobLogIds)); + } + + /** + * 清空定时任务调度日志 + */ + @RequiresPermissions("monitor:job:remove") + @Log(title = "调度日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + jobLogService.cleanJobLog(); + return success(); + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJob.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJob.java new file mode 100644 index 00000000..a2005163 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJob.java @@ -0,0 +1,171 @@ +package com.yanzhu.job.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.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.constant.ScheduleConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.domain.BaseEntity; +import com.yanzhu.job.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(); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJobLog.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJobLog.java new file mode 100644 index 00000000..302a2826 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/domain/SysJobLog.java @@ -0,0 +1,155 @@ +package com.yanzhu.job.domain; + +import java.util.Date; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.web.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobLogMapper.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobLogMapper.java new file mode 100644 index 00000000..1b9c37bc --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobLogMapper.java @@ -0,0 +1,64 @@ +package com.yanzhu.job.mapper; + +import java.util.List; +import com.yanzhu.job.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobMapper.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobMapper.java new file mode 100644 index 00000000..1b7b768d --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/mapper/SysJobMapper.java @@ -0,0 +1,67 @@ +package com.yanzhu.job.mapper; + +import java.util.List; +import com.yanzhu.job.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobLogService.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobLogService.java new file mode 100644 index 00000000..ab220e0a --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobLogService.java @@ -0,0 +1,56 @@ +package com.yanzhu.job.service; + +import java.util.List; +import com.yanzhu.job.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobService.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobService.java new file mode 100644 index 00000000..0ba0b42f --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/ISysJobService.java @@ -0,0 +1,103 @@ +package com.yanzhu.job.service; + +import java.util.List; + +import com.yanzhu.job.domain.SysJob; +import org.quartz.SchedulerException; +import com.yanzhu.common.core.exception.job.TaskException; + +/** + * 定时任务调度信息信息 服务层 + * + * @author ruoyi + */ +public interface ISysJobService +{ + /** + * 获取quartz调度器的计划任务 + * + * @param job 调度信息 + * @return 调度任务集合 + */ + public List selectJobList(SysJob job); + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + public SysJob selectJobById(Long jobId); + + /** + * 暂停任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int pauseJob(SysJob job) throws SchedulerException; + + /** + * 恢复任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int resumeJob(SysJob job) throws SchedulerException; + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + * @return 结果 + */ + public int deleteJob(SysJob job) throws SchedulerException; + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + public void deleteJobByIds(Long[] jobIds) throws SchedulerException; + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + * @return 结果 + */ + public int changeStatus(SysJob job) throws SchedulerException; + + /** + * 立即运行任务 + * + * @param job 调度信息 + * @return 结果 + */ + public boolean run(SysJob job) throws SchedulerException; + + /** + * 新增任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int insertJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 更新任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int updateJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + public boolean checkCronExpressionIsValid(String cronExpression); +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobLogServiceImpl.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobLogServiceImpl.java new file mode 100644 index 00000000..25e74758 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobLogServiceImpl.java @@ -0,0 +1,87 @@ +package com.yanzhu.job.service; + +import java.util.List; + +import com.yanzhu.job.domain.SysJobLog; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.job.mapper.SysJobLogMapper; + +/** + * 定时任务调度日志信息 服务层 + * + * @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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobServiceImpl.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobServiceImpl.java new file mode 100644 index 00000000..15b5470f --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/service/SysJobServiceImpl.java @@ -0,0 +1,261 @@ +package com.yanzhu.job.service; + +import java.util.List; +import javax.annotation.PostConstruct; + +import com.yanzhu.job.domain.SysJob; +import com.yanzhu.job.mapper.SysJobMapper; +import com.yanzhu.job.util.CronUtils; +import com.yanzhu.job.util.ScheduleUtils; +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.yanzhu.common.core.constant.ScheduleConstants; +import com.yanzhu.common.core.exception.job.TaskException; + +/** + * 定时任务调度信息 服务层 + * + * @author ruoyi + */ +@Service +public class SysJobServiceImpl implements ISysJobService +{ + @Autowired + private Scheduler scheduler; + + @Autowired + private SysJobMapper jobMapper; + + /** + * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) + */ + @PostConstruct + public void init() throws SchedulerException, TaskException + { + scheduler.clear(); + List jobList = jobMapper.selectJobAll(); + for (SysJob job : jobList) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + } + + /** + * 获取quartz调度器的计划任务列表 + * + * @param job 调度信息 + * @return + */ + @Override + public List selectJobList(SysJob job) + { + return jobMapper.selectJobList(job); + } + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + @Override + public SysJob selectJobById(Long jobId) + { + return jobMapper.selectJobById(jobId); + } + + /** + * 暂停任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int pauseJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 恢复任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int resumeJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + int rows = jobMapper.deleteJobById(jobId); + if (rows > 0) + { + scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteJobByIds(Long[] jobIds) throws SchedulerException + { + for (Long jobId : jobIds) + { + SysJob job = jobMapper.selectJobById(jobId); + deleteJob(job); + } + } + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int changeStatus(SysJob job) throws SchedulerException + { + int rows = 0; + String status = job.getStatus(); + if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) + { + rows = resumeJob(job); + } + else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) + { + rows = pauseJob(job); + } + return rows; + } + + /** + * 立即运行任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean run(SysJob job) throws SchedulerException + { + boolean result = false; + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + SysJob properties = selectJobById(job.getJobId()); + // 参数 + JobDataMap dataMap = new JobDataMap(); + dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + result = true; + scheduler.triggerJob(jobKey, dataMap); + } + return result; + } + + /** + * 新增任务 + * + * @param job 调度信息 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertJob(SysJob job) throws SchedulerException, TaskException + { + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.insertJob(job); + if (rows > 0) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + return rows; + } + + /** + * 更新任务的时间表达式 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateJob(SysJob job) throws SchedulerException, TaskException + { + SysJob properties = selectJobById(job.getJobId()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + updateSchedulerJob(job, properties.getJobGroup()); + } + return rows; + } + + /** + * 更新任务 + * + * @param job 任务对象 + * @param jobGroup 任务组名 + */ + public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException + { + Long jobId = job.getJobId(); + // 判断是否存在 + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(jobKey); + } + ScheduleUtils.createScheduleJob(scheduler, job); + } + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + @Override + public boolean checkCronExpressionIsValid(String cronExpression) + { + return CronUtils.isValid(cronExpression); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/task/RyTask.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/task/RyTask.java new file mode 100644 index 00000000..f1797cde --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/task/RyTask.java @@ -0,0 +1,28 @@ +package com.yanzhu.job.task; + +import org.springframework.stereotype.Component; +import com.yanzhu.common.core.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/AbstractQuartzJob.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/AbstractQuartzJob.java new file mode 100644 index 00000000..3b7aff13 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/AbstractQuartzJob.java @@ -0,0 +1,107 @@ +package com.yanzhu.job.util; + +import java.util.Date; + +import com.yanzhu.job.domain.SysJob; +import com.yanzhu.job.domain.SysJobLog; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.yanzhu.common.core.constant.ScheduleConstants; +import com.yanzhu.common.core.utils.ExceptionUtil; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.bean.BeanUtils; +import com.yanzhu.job.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("1"); + String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); + sysJobLog.setExceptionInfo(errorMsg); + } + else + { + sysJobLog.setStatus("0"); + } + + // 写入数据库当中 + 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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/CronUtils.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/CronUtils.java new file mode 100644 index 00000000..c67c8850 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/CronUtils.java @@ -0,0 +1,63 @@ +package com.yanzhu.job.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/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/JobInvokeUtil.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/JobInvokeUtil.java new file mode 100644 index 00000000..f711b3a1 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/JobInvokeUtil.java @@ -0,0 +1,182 @@ +package com.yanzhu.job.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.job.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().getMethod(methodName, getMethodParamsType(methodParams)); + method.invoke(bean, getMethodParamsValue(methodParams)); + } + else + { + Method method = bean.getClass().getMethod(methodName); + method.invoke(bean); + } + } + + /** + * 校验是否为为class包名 + * + * @param invokeTarget 名称 + * @return true是 false否 + */ + public static boolean isValidClassName(String invokeTarget) + { + return StringUtils.countMatches(invokeTarget, ".") > 1; + } + + /** + * 获取bean名称 + * + * @param invokeTarget 目标字符串 + * @return bean名称 + */ + public static String getBeanName(String invokeTarget) + { + String beanName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringBeforeLast(beanName, "."); + } + + /** + * 获取bean方法 + * + * @param invokeTarget 目标字符串 + * @return method方法 + */ + public static String getMethodName(String invokeTarget) + { + String methodName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringAfterLast(methodName, "."); + } + + /** + * 获取method方法参数相关列表 + * + * @param invokeTarget 目标字符串 + * @return method方法相关参数列表 + */ + public static List getMethodParams(String invokeTarget) + { + String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); + if (StringUtils.isEmpty(methodStr)) + { + return null; + } + String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); + List classs = new LinkedList<>(); + for (int i = 0; i < methodParams.length; i++) + { + String str = StringUtils.trimToEmpty(methodParams[i]); + // String字符串类型,以'或"开头 + if (StringUtils.startsWithAny(str, "'", "\"")) + { + classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class }); + } + // boolean布尔类型,等于true或者false + else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) + { + classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + } + // long长整形,以L结尾 + else if (StringUtils.endsWith(str, "L")) + { + classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class }); + } + // double浮点类型,以D结尾 + else if (StringUtils.endsWith(str, "D")) + { + classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class }); + } + // 其他类型归类为整形 + else + { + classs.add(new Object[] { Integer.valueOf(str), Integer.class }); + } + } + return classs; + } + + /** + * 获取参数类型 + * + * @param methodParams 参数相关列表 + * @return 参数类型列表 + */ + public static Class[] getMethodParamsType(List methodParams) + { + Class[] classs = new Class[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Class) os[1]; + index++; + } + return classs; + } + + /** + * 获取参数值 + * + * @param methodParams 参数相关列表 + * @return 参数值列表 + */ + public static Object[] getMethodParamsValue(List methodParams) + { + Object[] classs = new Object[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Object) os[0]; + index++; + } + return classs; + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzDisallowConcurrentExecution.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzDisallowConcurrentExecution.java new file mode 100644 index 00000000..7823a54c --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzDisallowConcurrentExecution.java @@ -0,0 +1,21 @@ +package com.yanzhu.job.util; + +import com.yanzhu.job.domain.SysJob; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; + +/** + * 定时任务处理(禁止并发执行) + * + * @author ruoyi + * + */ +@DisallowConcurrentExecution +public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzJobExecution.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzJobExecution.java new file mode 100644 index 00000000..978da32e --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/QuartzJobExecution.java @@ -0,0 +1,19 @@ +package com.yanzhu.job.util; + +import com.yanzhu.job.domain.SysJob; +import org.quartz.JobExecutionContext; + +/** + * 定时任务处理(允许并发执行) + * + * @author ruoyi + * + */ +public class QuartzJobExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/ScheduleUtils.java b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/ScheduleUtils.java new file mode 100644 index 00000000..5902a1bd --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/java/com/yanzhu/job/util/ScheduleUtils.java @@ -0,0 +1,139 @@ +package com.yanzhu.job.util; + +import com.yanzhu.job.domain.SysJob; +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.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.constant.ScheduleConstants; +import com.yanzhu.common.core.exception.job.TaskException; +import com.yanzhu.common.core.exception.job.TaskException.Code; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 定时任务工具类 + * + * @author ruoyi + * + */ +public class ScheduleUtils +{ + /** + * 得到quartz任务类 + * + * @param sysJob 执行计划 + * @return 具体执行任务类 + */ + private static Class getQuartzJobClass(SysJob sysJob) + { + boolean isConcurrent = "0".equals(sysJob.getConcurrent()); + return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; + } + + /** + * 构建任务触发对象 + */ + public static TriggerKey getTriggerKey(Long jobId, String jobGroup) + { + return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 构建任务键对象 + */ + public static JobKey getJobKey(Long jobId, String jobGroup) + { + return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException + { + Class jobClass = getQuartzJobClass(job); + // 构建job信息 + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); + + // 表达式调度构建器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); + cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); + + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) + .withSchedule(cronScheduleBuilder).build(); + + // 放入参数,运行时的方法可以获取 + jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); + + // 判断是否存在 + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(getJobKey(jobId, jobGroup)); + } + + // 判断任务是否过期 + if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) + { + // 执行调度任务 + scheduler.scheduleJob(jobDetail, trigger); + } + + // 暂停任务 + if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + } + + /** + * 设置定时任务策略 + */ + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb) + throws TaskException + { + switch (job.getMisfirePolicy()) + { + case ScheduleConstants.MISFIRE_DEFAULT: + return cb; + case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: + return cb.withMisfireHandlingInstructionIgnoreMisfires(); + case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: + return cb.withMisfireHandlingInstructionFireAndProceed(); + case ScheduleConstants.MISFIRE_DO_NOTHING: + return cb.withMisfireHandlingInstructionDoNothing(); + default: + throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + } + } + + /** + * 检查包名是否为白名单配置 + * + * @param invokeTarget 目标字符串 + * @return 结果 + */ + public static boolean whiteList(String invokeTarget) + { + String packageName = StringUtils.substringBefore(invokeTarget, "("); + int count = StringUtils.countMatches(packageName, "."); + if (count > 1) + { + return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); + } + Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); + return StringUtils.containsAnyIgnoreCase(obj.getClass().getPackage().getName(), Constants.JOB_WHITELIST_STR); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-job/src/main/resources/banner.txt new file mode 100644 index 00000000..0b9cd427 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ _ + (_) (_) | | + _ __ _ _ ___ _ _ _ ______ _ ___ | |__ +| '__|| | | | / _ \ | | | || ||______| | | / _ \ | '_ \ +| | | |_| || (_) || |_| || | | || (_) || |_) | +|_| \__,_| \___/ \__, ||_| | | \___/ |_.__/ + __/ | _/ | + |___/ |__/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-job/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..e5f3fed1 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9203 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-job + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-job/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-job/src/main/resources/logback.xml new file mode 100644 index 00000000..891c429a --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobLogMapper.xml b/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobLogMapper.xml new file mode 100644 index 00000000..2de8ab3f --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/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/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobMapper.xml b/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/SysJobMapper.xml new file mode 100644 index 00000000..659f1be3 --- /dev/null +++ b/yanzhu-modules/yanzhu-job/src/main/resources/mapper/job/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/yanzhu-modules/yanzhu-manage/pom.xml b/yanzhu-modules/yanzhu-manage/pom.xml new file mode 100644 index 00000000..ba81a1c9 --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/pom.xml @@ -0,0 +1,103 @@ + + + + yanzhu + com.yanzhu + 3.6.2 + ../../pom.xml + + 4.0.0 + + yanzhu-modules-manage + + + 17 + 17 + + + + yanzhu-modules-order订单模块 + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + org.apache.velocity + velocity-engine-core + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + + org.projectlombok + lombok + provided + + + + io.seata + seata-all + 1.5.2 + compile + + + + + com.yanzhu + yanzhu-common-mapper + 3.6.2 + compile + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/init b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/init b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/init b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-manage/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-manage/src/main/resources/banner.txt new file mode 100644 index 00000000..fbd45f53 --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ + (_) | | + _ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___ +| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \ +| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | | +|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_| + __/ | __/ | + |___/ |___/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..5cf7d0cb --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9206 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-manage + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-manage/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-manage/src/main/resources/logback.xml new file mode 100644 index 00000000..ee8d09d4 --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/pom.xml b/yanzhu-modules/yanzhu-system/pom.xml new file mode 100644 index 00000000..78bfc47f --- /dev/null +++ b/yanzhu-modules/yanzhu-system/pom.xml @@ -0,0 +1,155 @@ + + + + com.yanzhu + yanzhu-modules + 3.6.2 + + 4.0.0 + + yanzhu-modules-system + + + yanzhu-modules-system系统模块 + + + + + + + org.apache.shardingsphere + shardingsphere-jdbc-core-spring-boot-starter + 5.1.2 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-datasource + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + com.yanzhu + yanzhu-common-datascope + + + + io.seata + seata-all + 1.5.2 + compile + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-two-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/RuoYiSystemApplication.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/RuoYiSystemApplication.java new file mode 100644 index 00000000..4d24ce7e --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/RuoYiSystemApplication.java @@ -0,0 +1,34 @@ +package com.yanzhu.system; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 系统模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class RuoYiSystemApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiSystemApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysAreaController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysAreaController.java new file mode 100644 index 00000000..68cb10a1 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysAreaController.java @@ -0,0 +1,154 @@ +package com.yanzhu.system.controller; + +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.system.domain.SysArea; +import com.yanzhu.system.domain.vo.TreeSelect; +import com.yanzhu.system.service.ISysAreaService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 地址管理Controller + * + * @author JiangYuQi + * @date 2024-07-15 + */ +@RestController +@RequestMapping("/sysArea") +public class SysAreaController extends BaseController +{ + @Autowired + private RedisService redisService; + + @Autowired + private ISysAreaService sysAreaService; + + /** + * 查询地址管理列表 + */ + @RequiresPermissions("system:sysArea:list") + @GetMapping("/list") + public AjaxResult list(SysArea sysArea) + { + List list = sysAreaService.selectSysAreaList(sysArea); + return success(list); + } + + /** + * 刷新地址管理缓存 + */ + @RequiresPermissions("system:sysArea:list") + @GetMapping("/refreshCache") + public AjaxResult refreshCache() + { + sysAreaService.loadingSysAreaCache(); + return success(); + } + + /** + * 导出地址管理列表 + */ + @RequiresPermissions("system:sysArea:export") + @Log(title = "地址管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysArea sysArea) + { + List list = sysAreaService.selectSysAreaList(sysArea); + ExcelUtil util = new ExcelUtil(SysArea.class); + util.exportExcel(response, list, "地址管理数据"); + } + + /** + * 获取地址管理详细信息 + */ + @RequiresPermissions("system:sysArea:query") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") String id) + { + return success(sysAreaService.selectSysAreaById(id)); + } + + /** + * 新增地址管理 + */ + @RequiresPermissions("system:sysArea:add") + @Log(title = "地址管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysArea sysArea) + { + return toAjax(sysAreaService.insertSysArea(sysArea)); + } + + /** + * 修改地址管理 + */ + @RequiresPermissions("system:sysArea:edit") + @Log(title = "地址管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysArea sysArea) + { + return toAjax(sysAreaService.updateSysArea(sysArea)); + } + + /** + * 删除地址管理 + */ + @RequiresPermissions("system:sysArea:remove") + @Log(title = "地址管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable String[] ids) + { + return toAjax(sysAreaService.deleteSysAreaByIds(ids)); + } + + /** + * 查询区域地址列表 + */ + @GetMapping("/findAll") + public AjaxResult findAll() + { + // 基础数据访问频繁,加入到缓存 + String key = CacheConstants.SYS_AREA_ALL; + Object obj = redisService.getCacheObject(key); + if (obj != null) { + return success(obj); + }else{ + // 重新加载缓存信息 + sysAreaService.loadingSysAreaCache(); + obj = redisService.getCacheObject(key); + return success(obj); + } + } + + /** + * 查询城市地址列表 + */ + @GetMapping("/findAllCity") + public AjaxResult findAllCity() + { + // 基础数据访问频繁,加入到缓存 + String key = CacheConstants.SYS_AREA_CITY; + Object obj = redisService.getCacheObject(key); + if (obj != null) { + return success(obj); + }else{ + // 重新加载缓存信息 + SysArea area = new SysArea(); + area.setCtypeEvent(3); + List treeList = sysAreaService.selectAreaTreeList(area); + redisService.setCacheObject(key,treeList,CacheConstants.EXPIRATION, TimeUnit.MINUTES); + return success(treeList); + } + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysConfigController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysConfigController.java new file mode 100644 index 00000000..95877038 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysConfigController.java @@ -0,0 +1,133 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.domain.SysConfig; +import com.yanzhu.system.service.ISysConfigService; + +/** + * 参数配置 信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/config") +public class SysConfigController extends BaseController +{ + @Autowired + private ISysConfigService configService; + + /** + * 获取参数配置列表 + */ + @RequiresPermissions("system:config:list") + @GetMapping("/list") + public TableDataInfo list(SysConfig config) + { + startPage(); + List list = configService.selectConfigList(config); + return getDataTable(list); + } + + @Log(title = "参数管理", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:config:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysConfig config) + { + List list = configService.selectConfigList(config); + ExcelUtil util = new ExcelUtil(SysConfig.class); + util.exportExcel(response, list, "参数数据"); + } + + /** + * 根据参数编号获取详细信息 + */ + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long configId) + { + return success(configService.selectConfigById(configId)); + } + + /** + * 根据参数键名查询参数值 + */ + @GetMapping(value = "/configKey/{configKey}") + public AjaxResult getConfigKey(@PathVariable String configKey) + { + return success(configService.selectConfigByKey(configKey)); + } + + /** + * 新增参数配置 + */ + @RequiresPermissions("system:config:add") + @Log(title = "参数管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysConfig config) + { + if (!configService.checkConfigKeyUnique(config)) + { + return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setCreateBy(SecurityUtils.getUsername()); + return toAjax(configService.insertConfig(config)); + } + + /** + * 修改参数配置 + */ + @RequiresPermissions("system:config:edit") + @Log(title = "参数管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysConfig config) + { + if (!configService.checkConfigKeyUnique(config)) + { + return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(configService.updateConfig(config)); + } + + /** + * 删除参数配置 + */ + @RequiresPermissions("system:config:remove") + @Log(title = "参数管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{configIds}") + public AjaxResult remove(@PathVariable Long[] configIds) + { + configService.deleteConfigByIds(configIds); + return success(); + } + + /** + * 刷新参数缓存 + */ + @RequiresPermissions("system:config:remove") + @Log(title = "参数管理", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + configService.resetConfigCache(); + return success(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDeptController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDeptController.java new file mode 100644 index 00000000..d55d69b6 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDeptController.java @@ -0,0 +1,133 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.service.ISysDeptService; + +/** + * 部门信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/dept") +public class SysDeptController extends BaseController +{ + @Autowired + private ISysDeptService deptService; + + /** + * 获取部门列表 + */ + @RequiresPermissions("system:dept:list") + @GetMapping("/list") + public AjaxResult list(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return success(depts); + } + + /** + * 查询部门列表(排除节点) + */ + @RequiresPermissions("system:dept:list") + @GetMapping("/list/exclude/{deptId}") + public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) + { + List depts = deptService.selectDeptList(new SysDept()); + depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); + return success(depts); + } + + /** + * 根据部门编号获取详细信息 + */ + @RequiresPermissions("system:dept:query") + @GetMapping(value = "/{deptId}") + public AjaxResult getInfo(@PathVariable Long deptId) + { + deptService.checkDeptDataScope(deptId); + return success(deptService.selectDeptById(deptId)); + } + + /** + * 新增部门 + */ + @RequiresPermissions("system:dept:add") + @Log(title = "部门管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDept dept) + { + if (!deptService.checkDeptNameUnique(dept)) + { + return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + dept.setCreateBy(SecurityUtils.getUsername()); + return toAjax(deptService.insertDept(dept)); + } + + /** + * 修改部门 + */ + @RequiresPermissions("system:dept:edit") + @Log(title = "部门管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDept dept) + { + Long deptId = dept.getDeptId(); + deptService.checkDeptDataScope(deptId); + if (!deptService.checkDeptNameUnique(dept)) + { + return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + else if (dept.getParentId().equals(deptId)) + { + return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } + else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) + { + return error("该部门包含未停用的子部门!"); + } + dept.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(deptService.updateDept(dept)); + } + + /** + * 删除部门 + */ + @RequiresPermissions("system:dept:remove") + @Log(title = "部门管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{deptId}") + public AjaxResult remove(@PathVariable Long deptId) + { + if (deptService.hasChildByDeptId(deptId)) + { + return warn("存在下级部门,不允许删除"); + } + if (deptService.checkDeptExistUser(deptId)) + { + return warn("部门存在用户,不允许删除"); + } + deptService.checkDeptDataScope(deptId); + return toAjax(deptService.deleteDeptById(deptId)); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictDataController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictDataController.java new file mode 100644 index 00000000..ffb52516 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictDataController.java @@ -0,0 +1,122 @@ +package com.yanzhu.system.controller; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDictData; +import com.yanzhu.system.service.ISysDictDataService; +import com.yanzhu.system.service.ISysDictTypeService; + +/** + * 数据字典信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/dict/data") +public class SysDictDataController extends BaseController +{ + @Autowired + private ISysDictDataService dictDataService; + + @Autowired + private ISysDictTypeService dictTypeService; + + @RequiresPermissions("system:dict:list") + @GetMapping("/list") + public TableDataInfo list(SysDictData dictData) + { + startPage(); + List list = dictDataService.selectDictDataList(dictData); + return getDataTable(list); + } + + @Log(title = "字典数据", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:dict:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictData dictData) + { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil util = new ExcelUtil(SysDictData.class); + util.exportExcel(response, list, "字典数据"); + } + + /** + * 查询字典数据详细 + */ + @RequiresPermissions("system:dict:query") + @GetMapping(value = "/{dictCode}") + public AjaxResult getInfo(@PathVariable Long dictCode) + { + return success(dictDataService.selectDictDataById(dictCode)); + } + + /** + * 根据字典类型查询字典数据信息 + */ + @GetMapping(value = "/type/{dictType}") + public AjaxResult dictType(@PathVariable String dictType) + { + List data = dictTypeService.selectDictDataByType(dictType); + if (StringUtils.isNull(data)) + { + data = new ArrayList(); + } + return success(data); + } + + /** + * 新增字典类型 + */ + @RequiresPermissions("system:dict:add") + @Log(title = "字典数据", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictData dict) + { + dict.setCreateBy(SecurityUtils.getUsername()); + return toAjax(dictDataService.insertDictData(dict)); + } + + /** + * 修改保存字典类型 + */ + @RequiresPermissions("system:dict:edit") + @Log(title = "字典数据", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictData dict) + { + dict.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(dictDataService.updateDictData(dict)); + } + + /** + * 删除字典类型 + */ + @RequiresPermissions("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictCodes}") + public AjaxResult remove(@PathVariable Long[] dictCodes) + { + dictDataService.deleteDictDataByIds(dictCodes); + return success(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictTypeController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictTypeController.java new file mode 100644 index 00000000..9527dbc9 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysDictTypeController.java @@ -0,0 +1,132 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDictType; +import com.yanzhu.system.service.ISysDictTypeService; + +/** + * 数据字典信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/dict/type") +public class SysDictTypeController extends BaseController +{ + @Autowired + private ISysDictTypeService dictTypeService; + + @RequiresPermissions("system:dict:list") + @GetMapping("/list") + public TableDataInfo list(SysDictType dictType) + { + startPage(); + List list = dictTypeService.selectDictTypeList(dictType); + return getDataTable(list); + } + + @Log(title = "字典类型", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:dict:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictType dictType) + { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil util = new ExcelUtil(SysDictType.class); + util.exportExcel(response, list, "字典类型"); + } + + /** + * 查询字典类型详细 + */ + @RequiresPermissions("system:dict:query") + @GetMapping(value = "/{dictId}") + public AjaxResult getInfo(@PathVariable Long dictId) + { + return success(dictTypeService.selectDictTypeById(dictId)); + } + + /** + * 新增字典类型 + */ + @RequiresPermissions("system:dict:add") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictType dict) + { + if (!dictTypeService.checkDictTypeUnique(dict)) + { + return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setCreateBy(SecurityUtils.getUsername()); + return toAjax(dictTypeService.insertDictType(dict)); + } + + /** + * 修改字典类型 + */ + @RequiresPermissions("system:dict:edit") + @Log(title = "字典类型", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictType dict) + { + if (!dictTypeService.checkDictTypeUnique(dict)) + { + return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(dictTypeService.updateDictType(dict)); + } + + /** + * 删除字典类型 + */ + @RequiresPermissions("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public AjaxResult remove(@PathVariable Long[] dictIds) + { + dictTypeService.deleteDictTypeByIds(dictIds); + return success(); + } + + /** + * 刷新字典缓存 + */ + @RequiresPermissions("system:dict:remove") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + dictTypeService.resetDictCache(); + return success(); + } + + /** + * 获取字典选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List dictTypes = dictTypeService.selectDictTypeAll(); + return success(dictTypes); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysLogininforController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysLogininforController.java new file mode 100644 index 00000000..5e6e9816 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysLogininforController.java @@ -0,0 +1,92 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.annotation.InnerAuth; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.system.api.domain.SysLogininfor; +import com.yanzhu.system.service.ISysLogininforService; + +/** + * 系统访问记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/logininfor") +public class SysLogininforController extends BaseController +{ + @Autowired + private ISysLogininforService logininforService; + + @Autowired + private RedisService redisService; + + @RequiresPermissions("system:logininfor:list") + @GetMapping("/list") + public TableDataInfo list(SysLogininfor logininfor) + { + startPage(); + List list = logininforService.selectLogininforList(logininfor); + return getDataTable(list); + } + + @Log(title = "登录日志", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:logininfor:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysLogininfor logininfor) + { + List list = logininforService.selectLogininforList(logininfor); + ExcelUtil util = new ExcelUtil(SysLogininfor.class); + util.exportExcel(response, list, "登录日志"); + } + + @RequiresPermissions("system:logininfor:remove") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{infoIds}") + public AjaxResult remove(@PathVariable Long[] infoIds) + { + return toAjax(logininforService.deleteLogininforByIds(infoIds)); + } + + @RequiresPermissions("system:logininfor:remove") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/clean") + public AjaxResult clean() + { + logininforService.cleanLogininfor(); + return success(); + } + + @RequiresPermissions("system:logininfor:unlock") + @Log(title = "账户解锁", businessType = BusinessType.OTHER) + @GetMapping("/unlock/{userName}") + public AjaxResult unlock(@PathVariable("userName") String userName) + { + redisService.deleteObject(CacheConstants.PWD_ERR_CNT_KEY + userName); + return success(); + } + + @InnerAuth + @PostMapping + public AjaxResult add(@RequestBody SysLogininfor logininfor) + { + return toAjax(logininforService.insertLogininfor(logininfor)); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysMenuController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysMenuController.java new file mode 100644 index 00000000..624c067e --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysMenuController.java @@ -0,0 +1,159 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.domain.SysMenu; +import com.yanzhu.system.service.ISysMenuService; + +/** + * 菜单信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/menu") +public class SysMenuController extends BaseController +{ + @Autowired + private ISysMenuService menuService; + + /** + * 获取菜单列表 + */ + @RequiresPermissions("system:menu:list") + @GetMapping("/list") + public AjaxResult list(SysMenu menu) + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuList(menu, userId); + return success(menus); + } + + /** + * 根据菜单编号获取详细信息 + */ + @RequiresPermissions("system:menu:query") + @GetMapping(value = "/{menuId}") + public AjaxResult getInfo(@PathVariable Long menuId) + { + return success(menuService.selectMenuById(menuId)); + } + + /** + * 获取菜单下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysMenu menu) + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuList(menu, userId); + return success(menuService.buildMenuTreeSelect(menus)); + } + + /** + * 加载对应角色菜单列表树 + */ + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuList(userId); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); + ajax.put("menus", menuService.buildMenuTreeSelect(menus)); + return ajax; + } + + /** + * 新增菜单 + */ + @RequiresPermissions("system:menu:add") + @Log(title = "菜单管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysMenu menu) + { + if (!menuService.checkMenuNameUnique(menu)) + { + return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + menu.setCreateBy(SecurityUtils.getUsername()); + return toAjax(menuService.insertMenu(menu)); + } + + /** + * 修改菜单 + */ + @RequiresPermissions("system:menu:edit") + @Log(title = "菜单管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysMenu menu) + { + if (!menuService.checkMenuNameUnique(menu)) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + else if (menu.getMenuId().equals(menu.getParentId())) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); + } + menu.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(menuService.updateMenu(menu)); + } + + /** + * 删除菜单 + */ + @RequiresPermissions("system:menu:remove") + @Log(title = "菜单管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{menuId}") + public AjaxResult remove(@PathVariable("menuId") Long menuId) + { + if (menuService.hasChildByMenuId(menuId)) + { + return warn("存在子菜单,不允许删除"); + } + if (menuService.checkMenuExistRole(menuId)) + { + return warn("菜单已分配,不允许删除"); + } + return toAjax(menuService.deleteMenuById(menuId)); + } + + /** + * 获取路由信息 + * + * @return 路由信息 + */ + @GetMapping("getRouters") + public AjaxResult getRouters() + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuTreeByUserId(userId); + return success(menuService.buildMenus(menus)); + } +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysNoticeController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysNoticeController.java new file mode 100644 index 00000000..8140bee2 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysNoticeController.java @@ -0,0 +1,92 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.domain.SysNotice; +import com.yanzhu.system.service.ISysNoticeService; + +/** + * 公告 信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/notice") +public class SysNoticeController extends BaseController +{ + @Autowired + private ISysNoticeService noticeService; + + /** + * 获取通知公告列表 + */ + @RequiresPermissions("system:notice:list") + @GetMapping("/list") + public TableDataInfo list(SysNotice notice) + { + startPage(); + List list = noticeService.selectNoticeList(notice); + return getDataTable(list); + } + + /** + * 根据通知公告编号获取详细信息 + */ + @RequiresPermissions("system:notice:query") + @GetMapping(value = "/{noticeId}") + public AjaxResult getInfo(@PathVariable Long noticeId) + { + return success(noticeService.selectNoticeById(noticeId)); + } + + /** + * 新增通知公告 + */ + @RequiresPermissions("system:notice:add") + @Log(title = "通知公告", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysNotice notice) + { + notice.setCreateBy(SecurityUtils.getUsername()); + return toAjax(noticeService.insertNotice(notice)); + } + + /** + * 修改通知公告 + */ + @RequiresPermissions("system:notice:edit") + @Log(title = "通知公告", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysNotice notice) + { + notice.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(noticeService.updateNotice(notice)); + } + + /** + * 删除通知公告 + */ + @RequiresPermissions("system:notice:remove") + @Log(title = "通知公告", businessType = BusinessType.DELETE) + @DeleteMapping("/{noticeIds}") + public AjaxResult remove(@PathVariable Long[] noticeIds) + { + return toAjax(noticeService.deleteNoticeByIds(noticeIds)); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysOperlogController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysOperlogController.java new file mode 100644 index 00000000..4433f153 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysOperlogController.java @@ -0,0 +1,78 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.InnerAuth; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.system.api.domain.SysOperLog; +import com.yanzhu.system.service.ISysOperLogService; + +/** + * 操作日志记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/operlog") +public class SysOperlogController extends BaseController +{ + @Autowired + private ISysOperLogService operLogService; + + @RequiresPermissions("system:operlog:list") + @GetMapping("/list") + public TableDataInfo list(SysOperLog operLog) + { + startPage(); + List list = operLogService.selectOperLogList(operLog); + return getDataTable(list); + } + + @Log(title = "操作日志", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:operlog:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysOperLog operLog) + { + List list = operLogService.selectOperLogList(operLog); + ExcelUtil util = new ExcelUtil(SysOperLog.class); + util.exportExcel(response, list, "操作日志"); + } + + @Log(title = "操作日志", businessType = BusinessType.DELETE) + @RequiresPermissions("system:operlog:remove") + @DeleteMapping("/{operIds}") + public AjaxResult remove(@PathVariable Long[] operIds) + { + return toAjax(operLogService.deleteOperLogByIds(operIds)); + } + + @RequiresPermissions("system:operlog:remove") + @Log(title = "操作日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + operLogService.cleanOperLog(); + return success(); + } + + @InnerAuth + @PostMapping + public AjaxResult add(@RequestBody SysOperLog operLog) + { + return toAjax(operLogService.insertOperlog(operLog)); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysPostController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysPostController.java new file mode 100644 index 00000000..10aa0432 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysPostController.java @@ -0,0 +1,130 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.domain.SysPost; +import com.yanzhu.system.service.ISysPostService; + +/** + * 岗位信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/post") +public class SysPostController extends BaseController +{ + @Autowired + private ISysPostService postService; + + /** + * 获取岗位列表 + */ + @RequiresPermissions("system:post:list") + @GetMapping("/list") + public TableDataInfo list(SysPost post) + { + startPage(); + List list = postService.selectPostList(post); + return getDataTable(list); + } + + @Log(title = "岗位管理", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:post:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysPost post) + { + List list = postService.selectPostList(post); + ExcelUtil util = new ExcelUtil(SysPost.class); + util.exportExcel(response, list, "岗位数据"); + } + + /** + * 根据岗位编号获取详细信息 + */ + @RequiresPermissions("system:post:query") + @GetMapping(value = "/{postId}") + public AjaxResult getInfo(@PathVariable Long postId) + { + return success(postService.selectPostById(postId)); + } + + /** + * 新增岗位 + */ + @RequiresPermissions("system:post:add") + @Log(title = "岗位管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysPost post) + { + if (!postService.checkPostNameUnique(post)) + { + return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (!postService.checkPostCodeUnique(post)) + { + return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setCreateBy(SecurityUtils.getUsername()); + return toAjax(postService.insertPost(post)); + } + + /** + * 修改岗位 + */ + @RequiresPermissions("system:post:edit") + @Log(title = "岗位管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysPost post) + { + if (!postService.checkPostNameUnique(post)) + { + return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (!postService.checkPostCodeUnique(post)) + { + return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(postService.updatePost(post)); + } + + /** + * 删除岗位 + */ + @RequiresPermissions("system:post:remove") + @Log(title = "岗位管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{postIds}") + public AjaxResult remove(@PathVariable Long[] postIds) + { + return toAjax(postService.deletePostByIds(postIds)); + } + + /** + * 获取岗位选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List posts = postService.selectPostAll(); + return success(posts); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysProfileController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysProfileController.java new file mode 100644 index 00000000..437ba9c8 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysProfileController.java @@ -0,0 +1,158 @@ +package com.yanzhu.system.controller; + +import java.util.Arrays; +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.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.file.FileTypeUtils; +import com.yanzhu.common.core.utils.file.MimeTypeUtils; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.service.TokenService; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.RemoteFileService; +import com.yanzhu.system.api.domain.SysFile; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.api.model.LoginUser; +import com.yanzhu.system.service.ISysUserService; + +/** + * 个人信息 业务处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/user/profile") +public class SysProfileController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private TokenService tokenService; + + @Autowired + private RemoteFileService remoteFileService; + + /** + * 个人信息 + */ + @GetMapping + public AjaxResult profile() + { + String username = SecurityUtils.getUsername(); + SysUser user = userService.selectUserByUserName(username); + AjaxResult ajax = AjaxResult.success(user); + ajax.put("roleGroup", userService.selectUserRoleGroup(username)); + ajax.put("postGroup", userService.selectUserPostGroup(username)); + return ajax; + } + + /** + * 修改用户 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult updateProfile(@RequestBody SysUser user) + { + LoginUser loginUser = SecurityUtils.getLoginUser(); + SysUser sysUser = loginUser.getSysUser(); + user.setUserName(sysUser.getUserName()); + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUserId(sysUser.getUserId()); + user.setPassword(null); + user.setAvatar(null); + user.setDeptId(null); + if (userService.updateUserProfile(user) > 0) + { + // 更新缓存用户信息 + loginUser.getSysUser().setNickName(user.getNickName()); + loginUser.getSysUser().setPhonenumber(user.getPhonenumber()); + loginUser.getSysUser().setEmail(user.getEmail()); + loginUser.getSysUser().setSex(user.getSex()); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改个人信息异常,请联系管理员"); + } + + /** + * 重置密码 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping("/updatePwd") + public AjaxResult updatePwd(String oldPassword, String newPassword) + { + String username = SecurityUtils.getUsername(); + SysUser user = userService.selectUserByUserName(username); + String password = user.getPassword(); + if (!SecurityUtils.matchesPassword(oldPassword, password)) + { + return error("修改密码失败,旧密码错误"); + } + if (SecurityUtils.matchesPassword(newPassword, password)) + { + return error("新密码不能与旧密码相同"); + } + if (userService.resetUserPwd(username, SecurityUtils.encryptPassword(newPassword)) > 0) + { + // 更新缓存用户密码 + LoginUser loginUser = SecurityUtils.getLoginUser(); + loginUser.getSysUser().setPassword(SecurityUtils.encryptPassword(newPassword)); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改密码异常,请联系管理员"); + } + + /** + * 头像上传 + */ + @Log(title = "用户头像", businessType = BusinessType.UPDATE) + @PostMapping("/avatar") + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) + { + if (!file.isEmpty()) + { + LoginUser loginUser = SecurityUtils.getLoginUser(); + String extension = FileTypeUtils.getExtension(file); + if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) + { + return error("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式"); + } + R fileResult = remoteFileService.upload(file); + if (StringUtils.isNull(fileResult) || StringUtils.isNull(fileResult.getData())) + { + return error("文件服务异常,请联系管理员"); + } + String url = fileResult.getData().getUrl(); + if (userService.updateUserAvatar(loginUser.getUsername(), url)) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("imgUrl", url); + // 更新缓存用户头像 + loginUser.getSysUser().setAvatar(url); + tokenService.setLoginUser(loginUser); + return ajax; + } + } + return error("上传图片异常,请联系管理员"); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysRoleController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysRoleController.java new file mode 100644 index 00000000..f79ac288 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysRoleController.java @@ -0,0 +1,239 @@ +package com.yanzhu.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +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.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.domain.SysUserRole; +import com.yanzhu.system.service.ISysDeptService; +import com.yanzhu.system.service.ISysRoleService; +import com.yanzhu.system.service.ISysUserService; + +/** + * 角色信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/role") +public class SysRoleController extends BaseController +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysDeptService deptService; + + @RequiresPermissions("system:role:list") + @GetMapping("/list") + public TableDataInfo list(SysRole role) + { + startPage(); + List list = roleService.selectRoleList(role); + return getDataTable(list); + } + + @Log(title = "角色管理", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:role:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysRole role) + { + List list = roleService.selectRoleList(role); + ExcelUtil util = new ExcelUtil(SysRole.class); + util.exportExcel(response, list, "角色数据"); + } + + /** + * 根据角色编号获取详细信息 + */ + @RequiresPermissions("system:role:query") + @GetMapping(value = "/{roleId}") + public AjaxResult getInfo(@PathVariable Long roleId) + { + roleService.checkRoleDataScope(roleId); + return success(roleService.selectRoleById(roleId)); + } + + /** + * 新增角色 + */ + @RequiresPermissions("system:role:add") + @Log(title = "角色管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysRole role) + { + if (!roleService.checkRoleNameUnique(role)) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (!roleService.checkRoleKeyUnique(role)) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setCreateBy(SecurityUtils.getUsername()); + return toAjax(roleService.insertRole(role)); + + } + + /** + * 修改保存角色 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + if (!roleService.checkRoleNameUnique(role)) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (!roleService.checkRoleKeyUnique(role)) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(roleService.updateRole(role)); + } + + /** + * 修改保存数据权限 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/dataScope") + public AjaxResult dataScope(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + return toAjax(roleService.authDataScope(role)); + } + + /** + * 状态修改 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + role.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(roleService.updateRoleStatus(role)); + } + + /** + * 删除角色 + */ + @RequiresPermissions("system:role:remove") + @Log(title = "角色管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{roleIds}") + public AjaxResult remove(@PathVariable Long[] roleIds) + { + return toAjax(roleService.deleteRoleByIds(roleIds)); + } + + /** + * 获取角色选择框列表 + */ + @RequiresPermissions("system:role:query") + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + return success(roleService.selectRoleAll()); + } + /** + * 查询已分配用户角色列表 + */ + @RequiresPermissions("system:role:list") + @GetMapping("/authUser/allocatedList") + public TableDataInfo allocatedList(SysUser user) + { + startPage(); + List list = userService.selectAllocatedList(user); + return getDataTable(list); + } + + /** + * 查询未分配用户角色列表 + */ + @RequiresPermissions("system:role:list") + @GetMapping("/authUser/unallocatedList") + public TableDataInfo unallocatedList(SysUser user) + { + startPage(); + List list = userService.selectUnallocatedList(user); + return getDataTable(list); + } + + /** + * 取消授权用户 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancel") + public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) + { + return toAjax(roleService.deleteAuthUser(userRole)); + } + + /** + * 批量取消授权用户 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancelAll") + public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) + { + return toAjax(roleService.deleteAuthUsers(roleId, userIds)); + } + + /** + * 批量选择用户授权 + */ + @RequiresPermissions("system:role:edit") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/selectAll") + public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) + { + roleService.checkRoleDataScope(roleId); + return toAjax(roleService.insertAuthUsers(roleId, userIds)); + } + + /** + * 获取对应角色部门树列表 + */ + @RequiresPermissions("system:role:query") + @GetMapping(value = "/deptTree/{roleId}") + public AjaxResult deptTree(@PathVariable("roleId") Long roleId) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); + return ajax; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserController.java new file mode 100644 index 00000000..e9b681c9 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserController.java @@ -0,0 +1,326 @@ +package com.yanzhu.system.controller; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.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.yanzhu.common.core.domain.R; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.poi.ExcelUtil; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.security.annotation.InnerAuth; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.api.model.LoginUser; +import com.yanzhu.system.service.ISysConfigService; +import com.yanzhu.system.service.ISysDeptService; +import com.yanzhu.system.service.ISysPermissionService; +import com.yanzhu.system.service.ISysPostService; +import com.yanzhu.system.service.ISysRoleService; +import com.yanzhu.system.service.ISysUserService; + +/** + * 用户信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/user") +public class SysUserController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysDeptService deptService; + + @Autowired + private ISysPostService postService; + + @Autowired + private ISysPermissionService permissionService; + + @Autowired + private ISysConfigService configService; + + /** + * 获取用户列表 + */ + @RequiresPermissions("system:user:list") + @GetMapping("/list") + public TableDataInfo list(SysUser user) + { + startPage(); + List list = userService.selectUserList(user); + return getDataTable(list); + } + + @Log(title = "用户管理", businessType = BusinessType.EXPORT) + @RequiresPermissions("system:user:export") + @PostMapping("/export") + public void export(HttpServletResponse response, SysUser user) + { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + util.exportExcel(response, list, "用户数据"); + } + + @Log(title = "用户管理", businessType = BusinessType.IMPORT) + @RequiresPermissions("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 = SecurityUtils.getUsername(); + String message = userService.importUser(userList, updateSupport, operName); + return success(message); + } + + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) throws IOException + { + ExcelUtil util = new ExcelUtil(SysUser.class); + util.importTemplateExcel(response, "用户数据"); + } + + /** + * 获取当前用户信息 + */ + @InnerAuth + @GetMapping("/info/{username}") + public R info(@PathVariable("username") String username) + { + SysUser sysUser = userService.selectUserByUserName(username); + if (StringUtils.isNull(sysUser)) + { + return R.fail("用户名或密码错误"); + } + // 角色集合 + Set roles = permissionService.getRolePermission(sysUser); + // 权限集合 + Set permissions = permissionService.getMenuPermission(sysUser); + LoginUser sysUserVo = new LoginUser(); + sysUserVo.setSysUser(sysUser); + sysUserVo.setRoles(roles); + sysUserVo.setPermissions(permissions); + return R.ok(sysUserVo); + } + + /** + * 注册用户信息 + */ + @InnerAuth + @PostMapping("/register") + public R register(@RequestBody SysUser sysUser) + { + String username = sysUser.getUserName(); + if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) + { + return R.fail("当前系统没有开启注册功能!"); + } + if (!userService.checkUserNameUnique(sysUser)) + { + return R.fail("保存用户'" + username + "'失败,注册账号已存在"); + } + return R.ok(userService.registerUser(sysUser)); + } + + /** + * 获取用户信息 + * + * @return 用户信息 + */ + @GetMapping("getInfo") + public AjaxResult getInfo() + { + SysUser user = userService.selectUserById(SecurityUtils.getUserId()); + // 角色集合 + Set roles = permissionService.getRolePermission(user); + // 权限集合 + Set permissions = permissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + return ajax; + } + + /** + * 根据用户编号获取详细信息 + */ + @RequiresPermissions("system:user:query") + @GetMapping(value = { "/", "/{userId}" }) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) + { + userService.checkUserDataScope(userId); + AjaxResult ajax = AjaxResult.success(); + List roles = roleService.selectRoleAll(); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("posts", postService.selectPostAll()); + if (StringUtils.isNotNull(userId)) + { + SysUser sysUser = userService.selectUserById(userId); + ajax.put(AjaxResult.DATA_TAG, sysUser); + ajax.put("postIds", postService.selectPostListByUserId(userId)); + ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); + } + return ajax; + } + + /** + * 新增用户 + */ + @RequiresPermissions("system:user:add") + @Log(title = "用户管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysUser user) + { + if (!userService.checkUserNameUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setCreateBy(SecurityUtils.getUsername()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + return toAjax(userService.insertUser(user)); + } + + /** + * 修改用户 + */ + @RequiresPermissions("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + if (!userService.checkUserNameUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.updateUser(user)); + } + + /** + * 删除用户 + */ + @RequiresPermissions("system:user:remove") + @Log(title = "用户管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) + { + return error("当前用户不能删除"); + } + return toAjax(userService.deleteUserByIds(userIds)); + } + + /** + * 重置密码 + */ + @RequiresPermissions("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public AjaxResult resetPwd(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.resetPwd(user)); + } + + /** + * 状态修改 + */ + @RequiresPermissions("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.updateUserStatus(user)); + } + + /** + * 根据用户编号获取授权角色 + */ + @RequiresPermissions("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; + } + + /** + * 用户授权角色 + */ + @RequiresPermissions("system:user:edit") + @Log(title = "用户管理", businessType = BusinessType.GRANT) + @PutMapping("/authRole") + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) + { + userService.checkUserDataScope(userId); + userService.insertUserAuth(userId, roleIds); + return success(); + } + + /** + * 获取部门树列表 + */ + @RequiresPermissions("system:user:list") + @GetMapping("/deptTree") + public AjaxResult deptTree(SysDept dept) + { + return success(deptService.selectDeptTreeList(dept)); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserOnlineController.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserOnlineController.java new file mode 100644 index 00000000..633ec04b --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/controller/SysUserOnlineController.java @@ -0,0 +1,83 @@ +package com.yanzhu.system.controller; + +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.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.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.web.controller.BaseController; +import com.yanzhu.common.core.web.domain.AjaxResult; +import com.yanzhu.common.core.web.page.TableDataInfo; +import com.yanzhu.common.log.annotation.Log; +import com.yanzhu.common.log.enums.BusinessType; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.common.security.annotation.RequiresPermissions; +import com.yanzhu.system.api.model.LoginUser; +import com.yanzhu.system.domain.SysUserOnline; +import com.yanzhu.system.service.ISysUserOnlineService; + +/** + * 在线用户监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/online") +public class SysUserOnlineController extends BaseController +{ + @Autowired + private ISysUserOnlineService userOnlineService; + + @Autowired + private RedisService redisService; + + @RequiresPermissions("monitor:online:list") + @GetMapping("/list") + public TableDataInfo list(String ipaddr, String userName) + { + Collection keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList(); + for (String key : keys) + { + LoginUser user = redisService.getCacheObject(key); + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + else if (StringUtils.isNotEmpty(ipaddr)) + { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + else if (StringUtils.isNotEmpty(userName)) + { + userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); + } + else + { + userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); + } + } + Collections.reverse(userOnlineList); + userOnlineList.removeAll(Collections.singleton(null)); + return getDataTable(userOnlineList); + } + + /** + * 强退用户 + */ + @RequiresPermissions("monitor:online:forceLogout") + @Log(title = "在线用户", businessType = BusinessType.FORCE) + @DeleteMapping("/{tokenId}") + public AjaxResult forceLogout(@PathVariable String tokenId) + { + redisService.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + return success(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysArea.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysArea.java new file mode 100644 index 00000000..74f0600e --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysArea.java @@ -0,0 +1,97 @@ +package com.yanzhu.system.domain; + +import com.yanzhu.common.core.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; + +import java.util.ArrayList; +import java.util.List; + +/** + * 地址管理对象 sys_area + * + * @author JiangYuQi + * @date 2024-07-15 + */ +public class SysArea extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 编号 */ + private Long id; + + /** 父编号编号 */ + private Long parentId; + + /** 区域名称 */ + @Excel(name = "区域名称") + private String cname; + + /** 区域类型 */ + @Excel(name = "区域类型") + private Integer ctype; + + private Integer ctypeEvent; + + /** 子菜单 */ + private List children = new ArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public Integer getCtype() { + return ctype; + } + + public void setCtype(Integer ctype) { + this.ctype = ctype; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public Integer getCtypeEvent() { + return ctypeEvent; + } + + public void setCtypeEvent(Integer ctypeEvent) { + this.ctypeEvent = ctypeEvent; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("parentId", getParentId()) + .append("cname", getCname()) + .append("ctype", getCtype()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysConfig.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysConfig.java new file mode 100644 index 00000000..6f9c4aa4 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysConfig.java @@ -0,0 +1,111 @@ +package com.yanzhu.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 参数配置表 sys_config + * + * @author ruoyi + */ +public class SysConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 参数主键 */ + @Excel(name = "参数主键", cellType = ColumnType.NUMERIC) + private Long configId; + + /** 参数名称 */ + @Excel(name = "参数名称") + private String configName; + + /** 参数键名 */ + @Excel(name = "参数键名") + private String configKey; + + /** 参数键值 */ + @Excel(name = "参数键值") + private String configValue; + + /** 系统内置(Y是 N否) */ + @Excel(name = "系统内置", readConverterExp = "Y=是,N=否") + private String configType; + + public Long getConfigId() + { + return configId; + } + + public void setConfigId(Long configId) + { + this.configId = configId; + } + + @NotBlank(message = "参数名称不能为空") + @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") + public String getConfigName() + { + return configName; + } + + public void setConfigName(String configName) + { + this.configName = configName; + } + + @NotBlank(message = "参数键名长度不能为空") + @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") + public String getConfigKey() + { + return configKey; + } + + public void setConfigKey(String configKey) + { + this.configKey = configKey; + } + + @NotBlank(message = "参数键值不能为空") + @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") + public String getConfigValue() + { + return configValue; + } + + public void setConfigValue(String configValue) + { + this.configValue = configValue; + } + + public String getConfigType() + { + return configType; + } + + public void setConfigType(String configType) + { + this.configType = configType; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("configId", getConfigId()) + .append("configName", getConfigName()) + .append("configKey", getConfigKey()) + .append("configValue", getConfigValue()) + .append("configType", getConfigType()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysMenu.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysMenu.java new file mode 100644 index 00000000..eca259ec --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysMenu.java @@ -0,0 +1,259 @@ +package com.yanzhu.system.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 菜单权限表 sys_menu + * + * @author ruoyi + */ +public class SysMenu extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 菜单ID */ + private Long menuId; + + /** 菜单名称 */ + private String menuName; + + /** 父菜单名称 */ + private String parentName; + + /** 父菜单ID */ + private Long parentId; + + /** 显示顺序 */ + private Integer orderNum; + + /** 路由地址 */ + private String path; + + /** 组件路径 */ + private String component; + + /** 路由参数 */ + private String query; + + /** 是否为外链(0是 1否) */ + private String isFrame; + + /** 是否缓存(0缓存 1不缓存) */ + private String isCache; + + /** 类型(M目录 C菜单 F按钮) */ + private String menuType; + + /** 显示状态(0显示 1隐藏) */ + private String visible; + + /** 菜单状态(0正常 1停用) */ + private String status; + + /** 权限字符串 */ + private String perms; + + /** 菜单图标 */ + private String icon; + + /** 子菜单 */ + private List children = new ArrayList(); + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @NotBlank(message = "菜单名称不能为空") + @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") + public String getMenuName() + { + return menuName; + } + + public void setMenuName(String menuName) + { + this.menuName = menuName; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public String getIsFrame() + { + return isFrame; + } + + public void setIsFrame(String isFrame) + { + this.isFrame = isFrame; + } + + public String getIsCache() + { + return isCache; + } + + public void setIsCache(String isCache) + { + this.isCache = isCache; + } + + @NotBlank(message = "菜单类型不能为空") + public String getMenuType() + { + return menuType; + } + + public void setMenuType(String menuType) + { + this.menuType = menuType; + } + + public String getVisible() + { + return visible; + } + + public void setVisible(String visible) + { + this.visible = visible; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") + public String getPerms() + { + return perms; + } + + public void setPerms(String perms) + { + this.perms = perms; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("menuId", getMenuId()) + .append("menuName", getMenuName()) + .append("parentId", getParentId()) + .append("orderNum", getOrderNum()) + .append("path", getPath()) + .append("component", getComponent()) + .append("isFrame", getIsFrame()) + .append("IsCache", getIsCache()) + .append("menuType", getMenuType()) + .append("visible", getVisible()) + .append("status ", getStatus()) + .append("perms", getPerms()) + .append("icon", getIcon()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysNotice.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysNotice.java new file mode 100644 index 00000000..34b61b7e --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysNotice.java @@ -0,0 +1,102 @@ +package com.yanzhu.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.web.domain.BaseEntity; +import com.yanzhu.common.core.xss.Xss; + +/** + * 通知公告表 sys_notice + * + * @author ruoyi + */ +public class SysNotice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 公告ID */ + private Long noticeId; + + /** 公告标题 */ + private String noticeTitle; + + /** 公告类型(1通知 2公告) */ + private String noticeType; + + /** 公告内容 */ + private String noticeContent; + + /** 公告状态(0正常 1关闭) */ + private String status; + + public Long getNoticeId() + { + return noticeId; + } + + public void setNoticeId(Long noticeId) + { + this.noticeId = noticeId; + } + + public void setNoticeTitle(String noticeTitle) + { + this.noticeTitle = noticeTitle; + } + + @Xss(message = "公告标题不能包含脚本字符") + @NotBlank(message = "公告标题不能为空") + @Size(min = 0, max = 50, message = "公告标题不能超过50个字符") + public String getNoticeTitle() + { + return noticeTitle; + } + + public void setNoticeType(String noticeType) + { + this.noticeType = noticeType; + } + + public String getNoticeType() + { + return noticeType; + } + + public void setNoticeContent(String noticeContent) + { + this.noticeContent = noticeContent; + } + + public String getNoticeContent() + { + return noticeContent; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("noticeId", getNoticeId()) + .append("noticeTitle", getNoticeTitle()) + .append("noticeType", getNoticeType()) + .append("noticeContent", getNoticeContent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysPost.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysPost.java new file mode 100644 index 00000000..bbdb295c --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysPost.java @@ -0,0 +1,124 @@ +package com.yanzhu.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.annotation.Excel.ColumnType; +import com.yanzhu.common.core.web.domain.BaseEntity; + +/** + * 岗位表 sys_post + * + * @author ruoyi + */ +public class SysPost extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 岗位序号 */ + @Excel(name = "岗位序号", cellType = ColumnType.NUMERIC) + private Long postId; + + /** 岗位编码 */ + @Excel(name = "岗位编码") + private String postCode; + + /** 岗位名称 */ + @Excel(name = "岗位名称") + private String postName; + + /** 岗位排序 */ + @Excel(name = "岗位排序") + private Integer postSort; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 用户是否存在此岗位标识 默认不存在 */ + private boolean flag = false; + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @NotBlank(message = "岗位编码不能为空") + @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") + public String getPostCode() + { + return postCode; + } + + public void setPostCode(String postCode) + { + this.postCode = postCode; + } + + @NotBlank(message = "岗位名称不能为空") + @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") + public String getPostName() + { + return postName; + } + + public void setPostName(String postName) + { + this.postName = postName; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getPostSort() + { + return postSort; + } + + public void setPostSort(Integer postSort) + { + this.postSort = postSort; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("postId", getPostId()) + .append("postCode", getPostCode()) + .append("postName", getPostName()) + .append("postSort", getPostSort()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleDept.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleDept.java new file mode 100644 index 00000000..8199cf07 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleDept.java @@ -0,0 +1,46 @@ +package com.yanzhu.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和部门关联 sys_role_dept + * + * @author ruoyi + */ +public class SysRoleDept +{ + /** 角色ID */ + private Long roleId; + + /** 部门ID */ + private Long deptId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("deptId", getDeptId()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleMenu.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleMenu.java new file mode 100644 index 00000000..082917fa --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysRoleMenu.java @@ -0,0 +1,46 @@ +package com.yanzhu.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和菜单关联 sys_role_menu + * + * @author ruoyi + */ +public class SysRoleMenu +{ + /** 角色ID */ + private Long roleId; + + /** 菜单ID */ + private Long menuId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("menuId", getMenuId()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserOnline.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserOnline.java new file mode 100644 index 00000000..aadf0a7d --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserOnline.java @@ -0,0 +1,100 @@ +package com.yanzhu.system.domain; + +/** + * 当前在线会话 + * + * @author ruoyi + */ +public class SysUserOnline +{ + /** 会话编号 */ + private String tokenId; + + /** 用户名称 */ + private String userName; + + /** 登录IP地址 */ + private String ipaddr; + + /** 登录地址 */ + private String loginLocation; + + /** 浏览器类型 */ + private String browser; + + /** 操作系统 */ + private String os; + + /** 登录时间 */ + private Long loginTime; + + public String getTokenId() + { + return tokenId; + } + + public void setTokenId(String tokenId) + { + this.tokenId = tokenId; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserPost.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserPost.java new file mode 100644 index 00000000..a18cd852 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserPost.java @@ -0,0 +1,46 @@ +package com.yanzhu.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和岗位关联 sys_user_post + * + * @author ruoyi + */ +public class SysUserPost +{ + /** 用户ID */ + private Long userId; + + /** 岗位ID */ + private Long postId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("postId", getPostId()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserRole.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserRole.java new file mode 100644 index 00000000..cedad492 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/SysUserRole.java @@ -0,0 +1,46 @@ +package com.yanzhu.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和角色关联 sys_user_role + * + * @author ruoyi + */ +public class SysUserRole +{ + /** 用户ID */ + private Long userId; + + /** 角色ID */ + private Long roleId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("roleId", getRoleId()) + .toString(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/MetaVo.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/MetaVo.java new file mode 100644 index 00000000..6e93a77c --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/MetaVo.java @@ -0,0 +1,106 @@ +package com.yanzhu.system.domain.vo; + +import com.yanzhu.common.core.utils.StringUtils; + +/** + * 路由显示信息 + * + * @author ruoyi + */ +public class MetaVo +{ + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + private String link; + + public MetaVo() + { + } + + public MetaVo(String title, String icon) + { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) + { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtils.ishttp(link)) + { + this.link = link; + } + } + + public boolean isNoCache() + { + return noCache; + } + + public void setNoCache(boolean noCache) + { + this.noCache = noCache; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public String getLink() + { + return link; + } + + public void setLink(String link) + { + this.link = link; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/RouterVo.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/RouterVo.java new file mode 100644 index 00000000..2e3b47f7 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/RouterVo.java @@ -0,0 +1,148 @@ +package com.yanzhu.system.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; + +/** + * 路由配置信息 + * + * @author ruoyi + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouterVo +{ + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public boolean getHidden() + { + return hidden; + } + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public String getRedirect() + { + return redirect; + } + + public void setRedirect(String redirect) + { + this.redirect = redirect; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public Boolean getAlwaysShow() + { + return alwaysShow; + } + + public void setAlwaysShow(Boolean alwaysShow) + { + this.alwaysShow = alwaysShow; + } + + public MetaVo getMeta() + { + return meta; + } + + public void setMeta(MetaVo meta) + { + this.meta = meta; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/TreeSelect.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/TreeSelect.java new file mode 100644 index 00000000..ca1059b3 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/domain/vo/TreeSelect.java @@ -0,0 +1,85 @@ +package com.yanzhu.system.domain.vo; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.domain.SysArea; +import com.yanzhu.system.domain.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 TreeSelect(SysArea area) + { + this.id = area.getId(); + this.label = area.getCname(); + this.children = area.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/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysAreaMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysAreaMapper.java new file mode 100644 index 00000000..863072b5 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysAreaMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysArea; + +/** + * 地址管理Mapper接口 + * + * @author JiangYuQi + * @date 2024-07-15 + */ +public interface SysAreaMapper +{ + /** + * 查询地址管理 + * + * @param id 地址管理主键 + * @return 地址管理 + */ + public SysArea selectSysAreaById(String id); + + /** + * 查询地址管理列表 + * + * @param sysArea 地址管理 + * @return 地址管理集合 + */ + public List selectSysAreaList(SysArea sysArea); + + /** + * 新增地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + public int insertSysArea(SysArea sysArea); + + /** + * 修改地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + public int updateSysArea(SysArea sysArea); + + /** + * 删除地址管理 + * + * @param id 地址管理主键 + * @return 结果 + */ + public int deleteSysAreaById(String id); + + /** + * 批量删除地址管理 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysAreaByIds(String[] ids); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysConfigMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysConfigMapper.java new file mode 100644 index 00000000..04f49114 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysConfigMapper.java @@ -0,0 +1,76 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysConfig; + +/** + * 参数配置 数据层 + * + * @author ruoyi + */ +public interface SysConfigMapper +{ + /** + * 查询参数配置信息 + * + * @param config 参数配置信息 + * @return 参数配置信息 + */ + public SysConfig selectConfig(SysConfig config); + + /** + * 通过ID查询配置 + * + * @param configId 参数ID + * @return 参数配置信息 + */ + public SysConfig selectConfigById(Long configId); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数配置信息 + */ + public SysConfig checkConfigKeyUnique(String configKey); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 删除参数配置 + * + * @param configId 参数ID + * @return 结果 + */ + public int deleteConfigById(Long configId); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + public int deleteConfigByIds(Long[] configIds); +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDeptMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDeptMapper.java new file mode 100644 index 00000000..6c7dc7f0 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDeptMapper.java @@ -0,0 +1,118 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.yanzhu.system.api.domain.SysDept; + +/** + * 部门管理 数据层 + * + * @author ruoyi + */ +public interface SysDeptMapper +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门 + * + * @param deptId 部门ID + * @return 部门列表 + */ + public List selectChildrenDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public int hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 + */ + public int checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param deptName 部门名称 + * @param parentId 父部门ID + * @return 结果 + */ + public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId); + + /** + * 新增部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 修改所在部门正常状态 + * + * @param deptIds 部门ID组 + */ + public void updateDeptStatusNormal(Long[] deptIds); + + /** + * 修改子元素关系 + * + * @param depts 子元素 + * @return 结果 + */ + public int updateDeptChildren(@Param("depts") List depts); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictDataMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictDataMapper.java new file mode 100644 index 00000000..24f7bcb0 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictDataMapper.java @@ -0,0 +1,95 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.yanzhu.system.api.domain.SysDictData; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +public interface SysDictDataMapper +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据 + */ + public int countDictDataByType(String dictType); + + /** + * 通过字典ID删除字典数据信息 + * + * @param dictCode 字典数据ID + * @return 结果 + */ + public int deleteDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); + + /** + * 同步修改字典类型 + * + * @param oldDictType 旧字典类型 + * @param newDictType 新旧字典类型 + * @return 结果 + */ + public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictTypeMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictTypeMapper.java new file mode 100644 index 00000000..17cbe3d2 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysDictTypeMapper.java @@ -0,0 +1,83 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.api.domain.SysDictType; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +public interface SysDictTypeMapper +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 通过字典ID删除字典信息 + * + * @param dictId 字典ID + * @return 结果 + */ + public int deleteDictTypeById(Long dictId); + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * 新增字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public SysDictType checkDictTypeUnique(String dictType); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysLogininforMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysLogininforMapper.java new file mode 100644 index 00000000..dbc571cf --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysLogininforMapper.java @@ -0,0 +1,42 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.api.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 数据层 + * + * @author ruoyi + */ +public interface SysLogininforMapper +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public int insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + * + * @return 结果 + */ + public int cleanLogininfor(); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysMenuMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysMenuMapper.java new file mode 100644 index 00000000..c8fdf97d --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysMenuMapper.java @@ -0,0 +1,126 @@ +package com.yanzhu.system.mapper; + +import java.util.List; + +import com.yanzhu.system.domain.SysMenu; +import org.apache.ibatis.annotations.Param; + +/** + * 菜单表 数据层 + * + * @author ruoyi + */ +public interface SysMenuMapper +{ + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu); + + /** + * 根据用户所有权限 + * + * @return 权限列表 + */ + public List selectMenuPerms(); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuListByUserId(SysMenu menu); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + public List selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public List selectMenuPermsByUserId(Long userId); + + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + public List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @param menuCheckStrictly 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int hasChildByMenuId(Long menuId); + + /** + * 新增菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menuName 菜单名称 + * @param parentId 父菜单ID + * @return 结果 + */ + public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysNoticeMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysNoticeMapper.java new file mode 100644 index 00000000..fdb74fe3 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysNoticeMapper.java @@ -0,0 +1,60 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysNotice; + +/** + * 通知公告表 数据层 + * + * @author ruoyi + */ +public interface SysNoticeMapper +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 批量删除公告 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysOperLogMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysOperLogMapper.java new file mode 100644 index 00000000..f2960c88 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysOperLogMapper.java @@ -0,0 +1,48 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.api.domain.SysOperLog; + +/** + * 操作日志 数据层 + * + * @author ruoyi + */ +public interface SysOperLogMapper +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + public int insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysPostMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysPostMapper.java new file mode 100644 index 00000000..aff0553d --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysPostMapper.java @@ -0,0 +1,99 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysPost; + +/** + * 岗位信息 数据层 + * + * @author ruoyi + */ +public interface SysPostMapper +{ + /** + * 查询岗位数据集合 + * + * @param post 岗位信息 + * @return 岗位数据集合 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public List selectPostsByUserName(String userName); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 修改岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); + + /** + * 新增岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 校验岗位名称 + * + * @param postName 岗位名称 + * @return 结果 + */ + public SysPost checkPostNameUnique(String postName); + + /** + * 校验岗位编码 + * + * @param postCode 岗位编码 + * @return 结果 + */ + public SysPost checkPostCodeUnique(String postCode); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleDeptMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleDeptMapper.java new file mode 100644 index 00000000..7253270d --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleDeptMapper.java @@ -0,0 +1,44 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysRoleDept; + +/** + * 角色与部门关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleDeptMapper +{ + /** + * 通过角色ID删除角色和部门关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批量删除角色部门关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleDept(Long[] ids); + + /** + * 查询部门使用数量 + * + * @param deptId 部门ID + * @return 结果 + */ + public int selectCountRoleDeptByDeptId(Long deptId); + + /** + * 批量新增角色部门信息 + * + * @param roleDeptList 角色部门列表 + * @return 结果 + */ + public int batchRoleDept(List roleDeptList); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMapper.java new file mode 100644 index 00000000..261822d2 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMapper.java @@ -0,0 +1,107 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.api.domain.SysRole; + +/** + * 角色表 数据层 + * + * @author ruoyi + */ +public interface SysRoleMapper +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 根据用户ID查询角色 + * + * @param userName 用户名 + * @return 角色列表 + */ + public List selectRolesByUserName(String userName); + + /** + * 校验角色名称是否唯一 + * + * @param roleName 角色名称 + * @return 角色信息 + */ + public SysRole checkRoleNameUnique(String roleName); + + /** + * 校验角色权限是否唯一 + * + * @param roleKey 角色权限 + * @return 角色信息 + */ + public SysRole checkRoleKeyUnique(String roleKey); + + /** + * 修改角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 新增角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMenuMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 00000000..172046b6 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysRoleMenuMapper.java @@ -0,0 +1,44 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysRoleMenu; + +/** + * 角色与菜单关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleMenuMapper +{ + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int checkMenuExistRole(Long menuId); + + /** + * 通过角色ID删除角色和菜单关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleMenuByRoleId(Long roleId); + + /** + * 批量删除角色菜单关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleMenu(Long[] ids); + + /** + * 批量新增角色菜单信息 + * + * @param roleMenuList 角色菜单列表 + * @return 结果 + */ + public int batchRoleMenu(List roleMenuList); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserMapper.java new file mode 100644 index 00000000..035985a0 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserMapper.java @@ -0,0 +1,127 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.yanzhu.system.api.domain.SysUser; + +/** + * 用户表 数据层 + * + * @author ruoyi + */ +public interface SysUserMapper +{ + /** + * 根据条件分页查询用户列表 + * + * @param sysUser 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser sysUser); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectAllocatedList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(@Param("userName") String userName, @Param("password") String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + public SysUser checkUserNameUnique(String userName); + + /** + * 校验手机号码是否唯一 + * + * @param phonenumber 手机号码 + * @return 结果 + */ + public SysUser checkPhoneUnique(String phonenumber); + + /** + * 校验email是否唯一 + * + * @param email 用户邮箱 + * @return 结果 + */ + public SysUser checkEmailUnique(String email); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserPostMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserPostMapper.java new file mode 100644 index 00000000..d8fefab5 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserPostMapper.java @@ -0,0 +1,44 @@ +package com.yanzhu.system.mapper; + +import java.util.List; +import com.yanzhu.system.domain.SysUserPost; + +/** + * 用户与岗位关联表 数据层 + * + * @author ruoyi + */ +public interface SysUserPostMapper +{ + /** + * 通过用户ID删除用户和岗位关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserPostByUserId(Long userId); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 批量删除用户和岗位关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserPost(Long[] ids); + + /** + * 批量新增用户岗位信息 + * + * @param userPostList 用户角色列表 + * @return 结果 + */ + public int batchUserPost(List userPostList); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserRoleMapper.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserRoleMapper.java new file mode 100644 index 00000000..94bf296a --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,63 @@ +package com.yanzhu.system.mapper; + +import java.util.List; + +import com.yanzhu.system.domain.SysUserRole; +import org.apache.ibatis.annotations.Param; + +/** + * 用户与角色关联表 数据层 + * + * @author ruoyi + */ +public interface SysUserRoleMapper +{ + /** + * 通过用户ID删除用户和角色关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserRoleByUserId(Long userId); + + /** + * 批量删除用户和角色关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserRole(Long[] ids); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 批量新增用户角色信息 + * + * @param userRoleList 用户角色列表 + * @return 结果 + */ + public int batchUserRole(List userRoleList); + + /** + * 删除用户和角色关联信息 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + public int deleteUserRoleInfo(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysAreaService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysAreaService.java new file mode 100644 index 00000000..5e8c04c3 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysAreaService.java @@ -0,0 +1,92 @@ +package com.yanzhu.system.service; + +import java.util.List; + +import com.yanzhu.system.domain.SysArea; +import com.yanzhu.system.domain.vo.TreeSelect; + +/** + * 地址管理Service接口 + * + * @author JiangYuQi + * @date 2024-07-15 + */ +public interface ISysAreaService +{ + /** + * 查询地址管理 + * + * @param id 地址管理主键 + * @return 地址管理 + */ + public SysArea selectSysAreaById(String id); + + /** + * 查询地址管理列表 + * + * @param sysArea 地址管理 + * @return 地址管理集合 + */ + public List selectSysAreaList(SysArea sysArea); + + /** + * 查询区域树结构信息 + * + * @param area 区域信息 + * @return 区域树信息集合 + */ + public List selectAreaTreeList(SysArea area); + + /** + * 构建前端所需要树结构 + * + * @param areas 区域列表 + * @return 树结构列表 + */ + public List buildAreaTree(List areas); + + /** + * 构建前端所需要下拉树结构 + * + * @param areas 区域列表 + * @return 下拉树结构列表 + */ + public List buildAreaTreeSelect(List areas); + + /** + * 加载参数缓存数据 + */ + public void loadingSysAreaCache(); + + /** + * 新增地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + public int insertSysArea(SysArea sysArea); + + /** + * 修改地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + public int updateSysArea(SysArea sysArea); + + /** + * 批量删除地址管理 + * + * @param ids 需要删除的地址管理主键集合 + * @return 结果 + */ + public int deleteSysAreaByIds(String[] ids); + + /** + * 删除地址管理信息 + * + * @param id 地址管理主键 + * @return 结果 + */ + public int deleteSysAreaById(String id); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysConfigService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysConfigService.java new file mode 100644 index 00000000..3e8e5c93 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysConfigService.java @@ -0,0 +1,82 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.domain.SysConfig; + +/** + * 参数配置 服务层 + * + * @author ruoyi + */ +public interface ISysConfigService +{ + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + public SysConfig selectConfigById(Long configId); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数键值 + */ + public String selectConfigByKey(String configKey); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + public void deleteConfigByIds(Long[] configIds); + + /** + * 加载参数缓存数据 + */ + public void loadingConfigCache(); + + /** + * 清空参数缓存数据 + */ + public void clearConfigCache(); + + /** + * 重置参数缓存数据 + */ + public void resetConfigCache(); + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + public boolean checkConfigKeyUnique(SysConfig config); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDeptService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDeptService.java new file mode 100644 index 00000000..bb036296 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDeptService.java @@ -0,0 +1,124 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.domain.vo.TreeSelect; + +/** + * 部门管理 服务层 + * + * @author ruoyi + */ +public interface ISysDeptService +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + public List selectDeptTreeList(SysDept dept); + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + public List buildDeptTree(List depts); + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + public List buildDeptTreeSelect(List depts); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(Long roleId); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + public boolean checkDeptNameUnique(SysDept dept); + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + public void checkDeptDataScope(Long deptId); + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictDataService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictDataService.java new file mode 100644 index 00000000..55896220 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictDataService.java @@ -0,0 +1,60 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysDictData; + +/** + * 字典 业务层 + * + * @author ruoyi + */ +public interface ISysDictDataService +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(String dictType, String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + public void deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictTypeService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictTypeService.java new file mode 100644 index 00000000..2f662b67 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysDictTypeService.java @@ -0,0 +1,98 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysDictData; +import com.yanzhu.system.api.domain.SysDictType; + +/** + * 字典 业务层 + * + * @author ruoyi + */ +public interface ISysDictTypeService +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + */ + public void deleteDictTypeByIds(Long[] dictIds); + + /** + * 加载字典缓存数据 + */ + public void loadingDictCache(); + + /** + * 清空字典缓存数据 + */ + public void clearDictCache(); + + /** + * 重置字典缓存数据 + */ + public void resetDictCache(); + + /** + * 新增保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public boolean checkDictTypeUnique(SysDictType dictType); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysLogininforService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysLogininforService.java new file mode 100644 index 00000000..8f374bf1 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysLogininforService.java @@ -0,0 +1,40 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 服务层 + * + * @author ruoyi + */ +public interface ISysLogininforService +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public int insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + */ + public void cleanLogininfor(); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysMenuService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysMenuService.java new file mode 100644 index 00000000..c87c0ea7 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysMenuService.java @@ -0,0 +1,144 @@ +package com.yanzhu.system.service; + +import java.util.List; +import java.util.Set; +import com.yanzhu.system.domain.SysMenu; +import com.yanzhu.system.domain.vo.RouterVo; +import com.yanzhu.system.domain.vo.TreeSelect; + +/** + * 菜单 业务层 + * + * @author ruoyi + */ +public interface ISysMenuService +{ + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(Long userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu, Long userId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectMenuPermsByUserId(Long userId); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + public Set selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(Long roleId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + public List buildMenus(List menus); + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + public List buildMenuTree(List menus); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + public List buildMenuTreeSelect(List menus); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean hasChildByMenuId(Long menuId); + + /** + * 查询菜单是否存在角色 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkMenuExistRole(Long menuId); + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean checkMenuNameUnique(SysMenu menu); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysNoticeService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysNoticeService.java new file mode 100644 index 00000000..41e41196 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysNoticeService.java @@ -0,0 +1,60 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.domain.SysNotice; + +/** + * 公告 服务层 + * + * @author ruoyi + */ +public interface ISysNoticeService +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 删除公告信息 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysOperLogService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysOperLogService.java new file mode 100644 index 00000000..c91737bf --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysOperLogService.java @@ -0,0 +1,49 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysOperLog; + +/** + * 操作日志 服务层 + * + * @author ruoyi + */ +public interface ISysOperLogService +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + * @return 结果 + */ + public int insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPermissionService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPermissionService.java new file mode 100644 index 00000000..69b92747 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPermissionService.java @@ -0,0 +1,29 @@ +package com.yanzhu.system.service; + +import java.util.Set; + +import com.yanzhu.system.api.domain.SysUser; + +/** + * 权限信息 服务层 + * + * @author ruoyi + */ +public interface ISysPermissionService +{ + /** + * 获取角色数据权限 + * + * @param userId 用户Id + * @return 角色权限信息 + */ + public Set getRolePermission(SysUser user); + + /** + * 获取菜单数据权限 + * + * @param userId 用户Id + * @return 菜单权限信息 + */ + public Set getMenuPermission(SysUser user); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPostService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPostService.java new file mode 100644 index 00000000..f8d5dee8 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysPostService.java @@ -0,0 +1,99 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.domain.SysPost; + +/** + * 岗位信息 服务层 + * + * @author ruoyi + */ +public interface ISysPostService +{ + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位列表 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + public boolean checkPostNameUnique(SysPost post); + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + public boolean checkPostCodeUnique(SysPost post); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysRoleService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysRoleService.java new file mode 100644 index 00000000..6941bd8a --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysRoleService.java @@ -0,0 +1,173 @@ +package com.yanzhu.system.service; + +import java.util.List; +import java.util.Set; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.domain.SysUserRole; + +/** + * 角色业务层 + * + * @author ruoyi + */ +public interface ISysRoleService +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolesByUserId(Long userId); + + /** + * 根据用户ID查询角色权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public boolean checkRoleNameUnique(SysRole role); + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public boolean checkRoleKeyUnique(SysRole role); + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + public void checkRoleAllowed(SysRole role); + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + public void checkRoleDataScope(Long roleId); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRoleStatus(SysRole role); + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int authDataScope(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + public int deleteAuthUser(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + public int deleteAuthUsers(Long roleId, Long[] userIds); + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + public int insertAuthUsers(Long roleId, Long[] userIds); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserOnlineService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserOnlineService.java new file mode 100644 index 00000000..414c7ebb --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserOnlineService.java @@ -0,0 +1,48 @@ +package com.yanzhu.system.service; + +import com.yanzhu.system.api.model.LoginUser; +import com.yanzhu.system.domain.SysUserOnline; + +/** + * 在线用户 服务层 + * + * @author ruoyi + */ +public interface ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user); + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user); + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user); + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + public SysUserOnline loginUserToUserOnline(LoginUser user); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserService.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserService.java new file mode 100644 index 00000000..562b0e58 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/ISysUserService.java @@ -0,0 +1,206 @@ +package com.yanzhu.system.service; + +import java.util.List; +import com.yanzhu.system.api.domain.SysUser; + +/** + * 用户 业务层 + * + * @author ruoyi + */ +public interface ISysUserService +{ + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser user); + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectAllocatedList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 根据用户ID查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserRoleGroup(String userName); + + /** + * 根据用户ID查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserPostGroup(String userName); + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean checkUserNameUnique(SysUser user); + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean checkPhoneUnique(SysUser user); + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean checkEmailUnique(SysUser user); + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + public void checkUserAllowed(SysUser user); + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + public void checkUserDataScope(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean registerUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserAuth(Long userId, Long[] roleIds); + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserStatus(SysUser user); + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserProfile(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public boolean updateUserAvatar(String userName, String avatar); + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + public int resetPwd(SysUser user); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(String userName, String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + public String importUser(List userList, Boolean isUpdateSupport, String operName); +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysAreaServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysAreaServiceImpl.java new file mode 100644 index 00000000..4b5669cb --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysAreaServiceImpl.java @@ -0,0 +1,221 @@ +package com.yanzhu.system.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.system.domain.vo.TreeSelect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.system.mapper.SysAreaMapper; +import com.yanzhu.system.domain.SysArea; +import com.yanzhu.system.service.ISysAreaService; + +import javax.annotation.PostConstruct; + +/** + * 地址管理Service业务层处理 + * + * @author JiangYuQi + * @date 2024-07-15 + */ +@Service +public class SysAreaServiceImpl implements ISysAreaService +{ + @Autowired + private RedisService redisService; + + @Autowired + private SysAreaMapper sysAreaMapper; + + /** + * 项目启动时,初始化参数到缓存 + */ + @PostConstruct + public void init() + { + loadingSysAreaCache(); + } + + /** + * 加载地址信息到缓存 + */ + @Override + public void loadingSysAreaCache(){ + SysArea area = new SysArea(); + List treeList = selectAreaTreeList(area); + redisService.setCacheObject(CacheConstants.SYS_AREA_ALL,treeList); + } + + /** + * 查询地址管理 + * + * @param id 地址管理主键 + * @return 地址管理 + */ + @Override + public SysArea selectSysAreaById(String id) + { + return sysAreaMapper.selectSysAreaById(id); + } + + /** + * 查询地址管理列表 + * + * @param sysArea 地址管理 + * @return 地址管理 + */ + @Override + public List selectSysAreaList(SysArea sysArea) + { + return sysAreaMapper.selectSysAreaList(sysArea); + } + + /** + * 查询区域树结构信息 + * + * @param area 区域信息 + * @return 区域树信息集合 + */ + @Override + public List selectAreaTreeList(SysArea area) + { + List areas = sysAreaMapper.selectSysAreaList(area); + return buildAreaTreeSelect(areas); + } + + /** + * 构建前端所需要树结构 + * + * @param areas 区域列表 + * @return 树结构列表 + */ + @Override + public List buildAreaTree(List areas) + { + List returnList = new ArrayList(); + List tempList = areas.stream().map(SysArea::getId).collect(Collectors.toList()); + for (SysArea area : areas) + { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(area.getParentId())) + { + recursionFn(areas, area); + returnList.add(area); + } + } + if (returnList.isEmpty()) + { + returnList = areas; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param areas 区域列表 + * @return 下拉树结构列表 + */ + @Override + public List buildAreaTreeSelect(List areas) + { + List areaTrees = buildAreaTree(areas); + return areaTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 新增地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + @Override + public int insertSysArea(SysArea sysArea) + { + return sysAreaMapper.insertSysArea(sysArea); + } + + /** + * 修改地址管理 + * + * @param sysArea 地址管理 + * @return 结果 + */ + @Override + public int updateSysArea(SysArea sysArea) + { + return sysAreaMapper.updateSysArea(sysArea); + } + + /** + * 批量删除地址管理 + * + * @param ids 需要删除的地址管理主键 + * @return 结果 + */ + @Override + public int deleteSysAreaByIds(String[] ids) + { + return sysAreaMapper.deleteSysAreaByIds(ids); + } + + /** + * 删除地址管理信息 + * + * @param id 地址管理主键 + * @return 结果 + */ + @Override + public int deleteSysAreaById(String id) + { + return sysAreaMapper.deleteSysAreaById(id); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysArea t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysArea tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysArea t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysArea n = (SysArea) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysArea t) + { + return getChildList(list, t).size() > 0 ? true : false; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysConfigServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 00000000..90d0444c --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,214 @@ +package com.yanzhu.system.service.impl; + +import java.util.Collection; +import java.util.List; +import javax.annotation.PostConstruct; + +import com.yanzhu.system.domain.SysConfig; +import com.yanzhu.system.mapper.SysConfigMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.constant.CacheConstants; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.redis.service.RedisService; +import com.yanzhu.system.service.ISysConfigService; + +/** + * 参数配置 服务层实现 + * + * @author ruoyi + */ +@Service +public class SysConfigServiceImpl implements ISysConfigService +{ + @Autowired + private SysConfigMapper configMapper; + + @Autowired + private RedisService redisService; + + /** + * 项目启动时,初始化参数到缓存 + */ + @PostConstruct + public void init() + { + loadingConfigCache(); + } + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + @Override + public SysConfig selectConfigById(Long configId) + { + SysConfig config = new SysConfig(); + config.setConfigId(configId); + return configMapper.selectConfig(config); + } + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数key + * @return 参数键值 + */ + @Override + public String selectConfigByKey(String configKey) + { + String configValue = Convert.toStr(redisService.getCacheObject(getCacheKey(configKey))); + if (StringUtils.isNotEmpty(configValue)) + { + return configValue; + } + SysConfig config = new SysConfig(); + config.setConfigKey(configKey); + SysConfig retConfig = configMapper.selectConfig(config); + if (StringUtils.isNotNull(retConfig)) + { + redisService.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); + return retConfig.getConfigValue(); + } + return StringUtils.EMPTY; + } + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + @Override + public List selectConfigList(SysConfig config) + { + return configMapper.selectConfigList(config); + } + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int insertConfig(SysConfig config) + { + int row = configMapper.insertConfig(config); + if (row > 0) + { + redisService.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int updateConfig(SysConfig config) + { + SysConfig temp = configMapper.selectConfigById(config.getConfigId()); + if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) + { + redisService.deleteObject(getCacheKey(temp.getConfigKey())); + } + + int row = configMapper.updateConfig(config); + if (row > 0) + { + redisService.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + @Override + public void deleteConfigByIds(Long[] configIds) + { + for (Long configId : configIds) + { + SysConfig config = selectConfigById(configId); + if (StringUtils.equals(UserConstants.YES, config.getConfigType())) + { + throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); + } + configMapper.deleteConfigById(configId); + redisService.deleteObject(getCacheKey(config.getConfigKey())); + } + } + + /** + * 加载参数缓存数据 + */ + @Override + public void loadingConfigCache() + { + List configsList = configMapper.selectConfigList(new SysConfig()); + for (SysConfig config : configsList) + { + redisService.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + } + + /** + * 清空参数缓存数据 + */ + @Override + public void clearConfigCache() + { + Collection keys = redisService.keys(CacheConstants.SYS_CONFIG_KEY + "*"); + redisService.deleteObject(keys); + } + + /** + * 重置参数缓存数据 + */ + @Override + public void resetConfigCache() + { + clearConfigCache(); + loadingConfigCache(); + } + + /** + * 校验参数键名是否唯一 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public boolean checkConfigKeyUnique(SysConfig config) + { + Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()); + if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + private String getCacheKey(String configKey) + { + return CacheConstants.SYS_CONFIG_KEY + configKey; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDeptServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 00000000..cd9000eb --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,339 @@ +package com.yanzhu.system.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import com.yanzhu.common.datascope.annotation.DataScope; +import com.yanzhu.system.domain.vo.TreeSelect; +import com.yanzhu.system.mapper.SysDeptMapper; +import com.yanzhu.system.mapper.SysRoleMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.text.Convert; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysDept; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.service.ISysDeptService; + +/** + * 部门管理 服务实现 + * + * @author ruoyi + */ +@Service +public class SysDeptServiceImpl implements ISysDeptService +{ + @Autowired + private SysDeptMapper deptMapper; + + @Autowired + private SysRoleMapper roleMapper; + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDept dept) + { + return deptMapper.selectDeptList(dept); + } + + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + @Override + public List selectDeptTreeList(SysDept dept) + { + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + return buildDeptTreeSelect(depts); + } + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + @Override + public List buildDeptTree(List depts) + { + List returnList = new ArrayList(); + List tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList()); + for (SysDept dept : depts) + { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(dept.getParentId())) + { + recursionFn(depts, dept); + returnList.add(dept); + } + } + if (returnList.isEmpty()) + { + returnList = depts; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List buildDeptTreeSelect(List depts) + { + List deptTrees = buildDeptTree(depts); + return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + @Override + public SysDept selectDeptById(Long deptId) + { + return deptMapper.selectDeptById(deptId); + } + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + @Override + public int selectNormalChildrenDeptById(Long deptId) + { + return deptMapper.selectNormalChildrenDeptById(deptId); + } + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) + { + int result = deptMapper.hasChildByDeptId(deptId); + return result > 0; + } + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkDeptExistUser(Long deptId) + { + int result = deptMapper.checkDeptExistUser(deptId); + return result > 0; + } + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public boolean checkDeptNameUnique(SysDept dept) + { + Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId(); + SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId()); + if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + @Override + public void checkDeptDataScope(Long deptId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysDept dept = new SysDept(); + dept.setDeptId(deptId); + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + if (StringUtils.isEmpty(depts)) + { + throw new ServiceException("没有权限访问部门数据!"); + } + } + } + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int insertDept(SysDept dept) + { + SysDept info = deptMapper.selectDeptById(dept.getParentId()); + // 如果父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) + { + throw new ServiceException("部门停用,不允许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + return deptMapper.insertDept(dept); + } + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int updateDept(SysDept dept) + { + SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId()); + SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId()); + if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) + { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + int result = deptMapper.updateDept(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals("0", dept.getAncestors())) + { + // 如果该部门是启用状态,则启用该部门的所有上级部门 + updateParentDeptStatusNormal(dept); + } + return result; + } + + /** + * 修改该部门的父级部门状态 + * + * @param dept 当前部门 + */ + private void updateParentDeptStatusNormal(SysDept dept) + { + String ancestors = dept.getAncestors(); + Long[] deptIds = Convert.toLongArray(ancestors); + deptMapper.updateDeptStatusNormal(deptIds); + } + + /** + * 修改子元素关系 + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) + { + List children = deptMapper.selectChildrenDeptById(deptId); + for (SysDept child : children) + { + child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + } + if (children.size() > 0) + { + deptMapper.updateDeptChildren(children); + } + } + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public int deleteDeptById(Long deptId) + { + return deptMapper.deleteDeptById(deptId); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDept t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDept tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysDept t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysDept n = (SysDept) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysDept t) + { + return getChildList(list, t).size() > 0 ? true : false; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictDataServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 00000000..e3fb90bf --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,112 @@ +package com.yanzhu.system.service.impl; + +import java.util.List; + +import com.yanzhu.system.mapper.SysDictDataMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.security.utils.DictUtils; +import com.yanzhu.system.api.domain.SysDictData; +import com.yanzhu.system.service.ISysDictDataService; + +/** + * 字典 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysDictDataServiceImpl implements ISysDictDataService +{ + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataList(SysDictData dictData) + { + return dictDataMapper.selectDictDataList(dictData); + } + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + @Override + public String selectDictLabel(String dictType, String dictValue) + { + return dictDataMapper.selectDictLabel(dictType, dictValue); + } + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + @Override + public SysDictData selectDictDataById(Long dictCode) + { + return dictDataMapper.selectDictDataById(dictCode); + } + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + @Override + public void deleteDictDataByIds(Long[] dictCodes) + { + for (Long dictCode : dictCodes) + { + SysDictData data = selectDictDataById(dictCode); + dictDataMapper.deleteDictDataById(dictCode); + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + } + + /** + * 新增保存字典数据信息 + * + * @param data 字典数据信息 + * @return 结果 + */ + @Override + public int insertDictData(SysDictData data) + { + int row = dictDataMapper.insertDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } + + /** + * 修改保存字典数据信息 + * + * @param data 字典数据信息 + * @return 结果 + */ + @Override + public int updateDictData(SysDictData data) + { + int row = dictDataMapper.updateDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictTypeServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 00000000..11f677c5 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,224 @@ +package com.yanzhu.system.service.impl; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; + +import com.yanzhu.system.mapper.SysDictDataMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.DictUtils; +import com.yanzhu.system.api.domain.SysDictData; +import com.yanzhu.system.api.domain.SysDictType; +import com.yanzhu.system.mapper.SysDictTypeMapper; +import com.yanzhu.system.service.ISysDictTypeService; + +/** + * 字典 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService +{ + @Autowired + private SysDictTypeMapper dictTypeMapper; + + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 项目启动时,初始化字典到缓存 + */ + @PostConstruct + public void init() + { + loadingDictCache(); + } + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeList(SysDictType dictType) + { + return dictTypeMapper.selectDictTypeList(dictType); + } + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeAll() + { + return dictTypeMapper.selectDictTypeAll(); + } + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataByType(String dictType) + { + List dictDatas = DictUtils.getDictCache(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + return dictDatas; + } + dictDatas = dictDataMapper.selectDictDataByType(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + DictUtils.setDictCache(dictType, dictDatas); + return dictDatas; + } + return null; + } + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeById(Long dictId) + { + return dictTypeMapper.selectDictTypeById(dictId); + } + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeByType(String dictType) + { + return dictTypeMapper.selectDictTypeByType(dictType); + } + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + */ + @Override + public void deleteDictTypeByIds(Long[] dictIds) + { + for (Long dictId : dictIds) + { + SysDictType dictType = selectDictTypeById(dictId); + if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName())); + } + dictTypeMapper.deleteDictTypeById(dictId); + DictUtils.removeDictCache(dictType.getDictType()); + } + } + + /** + * 加载字典缓存数据 + */ + @Override + public void loadingDictCache() + { + SysDictData dictData = new SysDictData(); + dictData.setStatus("0"); + Map> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getDictType)); + for (Map.Entry> entry : dictDataMap.entrySet()) + { + DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList())); + } + } + + /** + * 清空字典缓存数据 + */ + @Override + public void clearDictCache() + { + DictUtils.clearDictCache(); + } + + /** + * 重置字典缓存数据 + */ + @Override + public void resetDictCache() + { + clearDictCache(); + loadingDictCache(); + } + + /** + * 新增保存字典类型信息 + * + * @param dict 字典类型信息 + * @return 结果 + */ + @Override + public int insertDictType(SysDictType dict) + { + int row = dictTypeMapper.insertDictType(dict); + if (row > 0) + { + DictUtils.setDictCache(dict.getDictType(), null); + } + return row; + } + + /** + * 修改保存字典类型信息 + * + * @param dict 字典类型信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateDictType(SysDictType dict) + { + SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId()); + dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType()); + int row = dictTypeMapper.updateDictType(dict); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType()); + DictUtils.setDictCache(dict.getDictType(), dictDatas); + } + return row; + } + + /** + * 校验字典类型称是否唯一 + * + * @param dict 字典类型 + * @return 结果 + */ + @Override + public boolean checkDictTypeUnique(SysDictType dict) + { + Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId(); + SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType()); + if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysLogininforServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 00000000..91af7a5d --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysLogininforServiceImpl.java @@ -0,0 +1,65 @@ +package com.yanzhu.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.system.api.domain.SysLogininfor; +import com.yanzhu.system.mapper.SysLogininforMapper; +import com.yanzhu.system.service.ISysLogininforService; + +/** + * 系统访问日志情况信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysLogininforServiceImpl implements ISysLogininforService +{ + + @Autowired + private SysLogininforMapper logininforMapper; + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + @Override + public int insertLogininfor(SysLogininfor logininfor) + { + return logininforMapper.insertLogininfor(logininfor); + } + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + @Override + public List selectLogininforList(SysLogininfor logininfor) + { + return logininforMapper.selectLogininforList(logininfor); + } + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + @Override + public int deleteLogininforByIds(Long[] infoIds) + { + return logininforMapper.deleteLogininforByIds(infoIds); + } + + /** + * 清空系统登录日志 + */ + @Override + public void cleanLogininfor() + { + logininforMapper.cleanLogininfor(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysMenuServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 00000000..0f4d0445 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,532 @@ +package com.yanzhu.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.yanzhu.system.domain.SysMenu; +import com.yanzhu.system.domain.vo.MetaVo; +import com.yanzhu.system.domain.vo.RouterVo; +import com.yanzhu.system.domain.vo.TreeSelect; +import com.yanzhu.system.mapper.SysMenuMapper; +import com.yanzhu.system.mapper.SysRoleMapper; +import com.yanzhu.system.mapper.SysRoleMenuMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.constant.Constants; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.service.ISysMenuService; + +/** + * 菜单 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysMenuServiceImpl implements ISysMenuService +{ + public static final String PREMISSION_STRING = "perms[\"{0}\"]"; + + @Autowired + private SysMenuMapper menuMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuList(Long userId) + { + return selectMenuList(new SysMenu(), userId); + } + + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + @Override + public List selectMenuList(SysMenu menu, Long userId) + { + List menuList = null; + // 管理员显示所有菜单信息 + if (SysUser.isAdmin(userId)) + { + menuList = menuMapper.selectMenuList(menu); + } + else + { + menu.getParams().put("userId", userId); + menuList = menuMapper.selectMenuListByUserId(menu); + } + return menuList; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByUserId(Long userId) + { + List perms = menuMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByRoleId(Long roleId) + { + List perms = menuMapper.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户名称 + * @return 菜单列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) + { + List menus = null; + if (SecurityUtils.isAdmin(userId)) + { + menus = menuMapper.selectMenuTreeAll(); + } + else + { + menus = menuMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + @Override + public List buildMenus(List menus) + { + List routers = new LinkedList(); + for (SysMenu menu : menus) + { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setQuery(menu.getQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) + { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } + else if (isMenuFrame(menu)) + { + router.setMeta(null); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } + else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) + { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + String routerPath = innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + @Override + public List buildMenuTree(List menus) + { + List returnList = new ArrayList(); + List tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList()); + for (Iterator iterator = menus.iterator(); iterator.hasNext();) + { + SysMenu menu = (SysMenu) iterator.next(); + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(menu.getParentId())) + { + recursionFn(menus, menu); + returnList.add(menu); + } + } + if (returnList.isEmpty()) + { + returnList = menus; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + @Override + public List buildMenuTreeSelect(List menus) + { + List menuTrees = buildMenuTree(menus); + return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + @Override + public SysMenu selectMenuById(Long menuId) + { + return menuMapper.selectMenuById(menuId); + } + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) + { + int result = menuMapper.hasChildByMenuId(menuId); + return result > 0; + } + + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) + { + int result = roleMenuMapper.checkMenuExistRole(menuId); + return result > 0; + } + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int insertMenu(SysMenu menu) + { + return menuMapper.insertMenu(menu); + } + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int updateMenu(SysMenu menu) + { + return menuMapper.updateMenu(menu); + } + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public int deleteMenuById(Long menuId) + { + return menuMapper.deleteMenuById(menuId); + } + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public boolean checkMenuNameUnique(SysMenu menu) + { + Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); + SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); + if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 获取路由名称 + * + * @param menu 菜单信息 + * @return 路由名称 + */ + public String getRouteName(SysMenu menu) + { + String routerName = StringUtils.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为目录) + if (isMenuFrame(menu)) + { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 获取路由地址 + * + * @param menu 菜单信息 + * @return 路由地址 + */ + public String getRouterPath(SysMenu menu) + { + String routerPath = menu.getPath(); + // 内链打开外网方式 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + routerPath = innerLinkReplaceEach(routerPath); + } + // 非外链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) + { + routerPath = "/" + menu.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMenuFrame(menu)) + { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获取组件信息 + * + * @param menu 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenu menu) + { + String component = UserConstants.LAYOUT; + if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) + { + component = menu.getComponent(); + } + else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + component = UserConstants.INNER_LINK; + } + else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) + { + component = UserConstants.PARENT_VIEW; + } + return component; + } + + /** + * 是否为菜单内部跳转 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isMenuFrame(SysMenu menu) + { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 是否为内链组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isInnerLink(SysMenu menu) + { + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); + } + + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isParentView(SysMenu menu) + { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * 根据父节点的ID获取所有子节点 + * + * @param list 分类表 + * @param parentId 传入的父节点ID + * @return String + */ + public List getChildPerms(List list, int parentId) + { + List returnList = new ArrayList(); + for (Iterator iterator = list.iterator(); iterator.hasNext();) + { + SysMenu t = (SysMenu) iterator.next(); + // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 + if (t.getParentId() == parentId) + { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } + + /** + * 递归列表 + * + * @param list + * @param t + */ + private void recursionFn(List list, SysMenu t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysMenu tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysMenu t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysMenu n = (SysMenu) it.next(); + if (n.getParentId().longValue() == t.getMenuId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysMenu t) + { + return getChildList(list, t).size() > 0; + } + + /** + * 内链域名特殊字符替换 + * + * @return + */ + public String innerLinkReplaceEach(String path) + { + return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." }, + new String[] { "", "", "", "/" }); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysNoticeServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 00000000..79af71e6 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,93 @@ +package com.yanzhu.system.service.impl; + +import java.util.List; + +import com.yanzhu.system.domain.SysNotice; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.system.mapper.SysNoticeMapper; +import com.yanzhu.system.service.ISysNoticeService; + +/** + * 公告 服务层实现 + * + * @author ruoyi + */ +@Service +public class SysNoticeServiceImpl implements ISysNoticeService +{ + @Autowired + private SysNoticeMapper noticeMapper; + + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + @Override + public SysNotice selectNoticeById(Long noticeId) + { + return noticeMapper.selectNoticeById(noticeId); + } + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + @Override + public List selectNoticeList(SysNotice notice) + { + return noticeMapper.selectNoticeList(notice); + } + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int insertNotice(SysNotice notice) + { + return noticeMapper.insertNotice(notice); + } + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int updateNotice(SysNotice notice) + { + return noticeMapper.updateNotice(notice); + } + + /** + * 删除公告对象 + * + * @param noticeId 公告ID + * @return 结果 + */ + @Override + public int deleteNoticeById(Long noticeId) + { + return noticeMapper.deleteNoticeById(noticeId); + } + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + @Override + public int deleteNoticeByIds(Long[] noticeIds) + { + return noticeMapper.deleteNoticeByIds(noticeIds); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysOperLogServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 00000000..cc3c7449 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysOperLogServiceImpl.java @@ -0,0 +1,84 @@ +package com.yanzhu.system.service.impl; + +import java.util.List; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.yanzhu.system.mapper.SysOperLogMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.system.api.domain.SysOperLog; +import com.yanzhu.system.service.ISysOperLogService; + +/** + * 操作日志 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysOperLogServiceImpl implements ISysOperLogService +{ + @Autowired + private SysOperLogMapper operLogMapper; + + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + * @return 结果 + */ + @Override + @DS("sharding") + public int insertOperlog(SysOperLog operLog) + { + return operLogMapper.insertOperlog(operLog); + } + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + @Override + @DS("sharding") + public List selectOperLogList(SysOperLog operLog) + { + return operLogMapper.selectOperLogList(operLog); + } + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + @Override + @DS("sharding") + public int deleteOperLogByIds(Long[] operIds) + { + return operLogMapper.deleteOperLogByIds(operIds); + } + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + @Override + @DS("sharding") + public SysOperLog selectOperLogById(Long operId) + { + return operLogMapper.selectOperLogById(operId); + } + + /** + * 清空操作日志 + */ + @Override + @DS("sharding") + public void cleanOperLog() + { + operLogMapper.cleanOperLog(); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPermissionServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 00000000..5a7cc5b7 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,85 @@ +package com.yanzhu.system.service.impl; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.service.ISysMenuService; +import com.yanzhu.system.service.ISysPermissionService; +import com.yanzhu.system.service.ISysRoleService; + +/** + * 用户权限处理 + * + * @author ruoyi + */ +@Service +public class SysPermissionServiceImpl implements ISysPermissionService +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysMenuService menuService; + + /** + * 获取角色数据权限 + * + * @param userId 用户Id + * @return 角色权限信息 + */ + @Override + 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 userId 用户Id + * @return 菜单权限信息 + */ + @Override + public Set getMenuPermission(SysUser user) + { + Set perms = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + perms.add("*:*:*"); + } + else + { + List roles = user.getRoles(); + if (!roles.isEmpty() && roles.size() > 1) + { + // 多角色设置permissions属性,以便数据权限匹配权限 + for (SysRole role : roles) + { + Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); + role.setPermissions(rolePerms); + perms.addAll(rolePerms); + } + } + else + { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + } + return perms; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPostServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 00000000..74b040b4 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysPostServiceImpl.java @@ -0,0 +1,179 @@ +package com.yanzhu.system.service.impl; + +import java.util.List; + +import com.yanzhu.system.domain.SysPost; +import com.yanzhu.system.mapper.SysUserPostMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.system.mapper.SysPostMapper; +import com.yanzhu.system.service.ISysPostService; + +/** + * 岗位信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysPostServiceImpl implements ISysPostService +{ + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位信息集合 + */ + @Override + public List selectPostList(SysPost post) + { + return postMapper.selectPostList(post); + } + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + @Override + public List selectPostAll() + { + return postMapper.selectPostAll(); + } + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + @Override + public SysPost selectPostById(Long postId) + { + return postMapper.selectPostById(postId); + } + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) + { + return postMapper.selectPostListByUserId(userId); + } + + /** + * 校验岗位名称是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostNameUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostNameUnique(post.getPostName()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验岗位编码是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public boolean checkPostCodeUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostCodeUnique(post.getPostCode()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int countUserPostById(Long postId) + { + return userPostMapper.countUserPostById(postId); + } + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int deletePostById(Long postId) + { + return postMapper.deletePostById(postId); + } + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + @Override + public int deletePostByIds(Long[] postIds) + { + for (Long postId : postIds) + { + SysPost post = selectPostById(postId); + if (countUserPostById(postId) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName())); + } + } + return postMapper.deletePostByIds(postIds); + } + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int insertPost(SysPost post) + { + return postMapper.insertPost(post); + } + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int updatePost(SysPost post) + { + return postMapper.updatePost(post); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysRoleServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 00000000..376803e8 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,425 @@ +package com.yanzhu.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.yanzhu.common.datascope.annotation.DataScope; +import com.yanzhu.system.domain.SysRoleDept; +import com.yanzhu.system.domain.SysRoleMenu; +import com.yanzhu.system.domain.SysUserRole; +import com.yanzhu.system.mapper.SysRoleDeptMapper; +import com.yanzhu.system.mapper.SysRoleMapper; +import com.yanzhu.system.mapper.SysRoleMenuMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.mapper.SysUserRoleMapper; +import com.yanzhu.system.service.ISysRoleService; + +/** + * 角色 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysRoleServiceImpl implements ISysRoleService +{ + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysRoleDeptMapper roleDeptMapper; + + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + @Override + @DataScope(deptAlias = "d") + public List selectRoleList(SysRole role) + { + return roleMapper.selectRoleList(role); + } + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) + { + List userRoles = roleMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRole role : roles) + { + for (SysRole userRole : userRoles) + { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) + { + role.setFlag(true); + break; + } + } + } + return roles; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) + { + List perms = roleMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRole perm : perms) + { + if (StringUtils.isNotNull(perm)) + { + permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + @Override + public List selectRoleAll() + { + return SpringUtils.getAopProxy(this).selectRoleList(new SysRole()); + } + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) + { + return roleMapper.selectRoleListByUserId(userId); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + @Override + public SysRole selectRoleById(Long roleId) + { + return roleMapper.selectRoleById(roleId); + } + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleNameUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public boolean checkRoleKeyUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + @Override + public void checkRoleAllowed(SysRole role) + { + if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) + { + throw new ServiceException("不允许操作超级管理员角色"); + } + } + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysRole role = new SysRole(); + role.setRoleId(roleId); + List roles = SpringUtils.getAopProxy(this).selectRoleList(role); + if (StringUtils.isEmpty(roles)) + { + throw new ServiceException("没有权限访问角色数据!"); + } + } + } + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public int countUserRoleByRoleId(Long roleId) + { + return userRoleMapper.countUserRoleByRoleId(roleId); + } + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertRole(SysRole role) + { + // 新增角色信息 + roleMapper.insertRole(role); + return insertRoleMenu(role); + } + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateRole(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + return insertRoleMenu(role); + } + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public int updateRoleStatus(SysRole role) + { + return roleMapper.updateRole(role); + } + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int authDataScope(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信息(数据权限) + return insertRoleDept(role); + } + + /** + * 新增角色菜单信息 + * + * @param role 角色对象 + */ + public int insertRoleMenu(SysRole role) + { + int rows = 1; + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long menuId : role.getMenuIds()) + { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) + { + rows = roleMenuMapper.batchRoleMenu(list); + } + return rows; + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role 角色对象 + */ + public int insertRoleDept(SysRole role) + { + int rows = 1; + // 新增角色与部门(数据权限)管理 + List list = new ArrayList(); + for (Long deptId : role.getDeptIds()) + { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) + { + rows = roleDeptMapper.batchRoleDept(list); + } + return rows; + } + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteRoleById(Long roleId) + { + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(roleId); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(roleId); + return roleMapper.deleteRoleById(roleId); + } + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteRoleByIds(Long[] roleIds) + { + for (Long roleId : roleIds) + { + checkRoleAllowed(new SysRole(roleId)); + checkRoleDataScope(roleId); + SysRole role = selectRoleById(roleId); + if (countUserRoleByRoleId(roleId) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenu(roleIds); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDept(roleIds); + return roleMapper.deleteRoleByIds(roleIds); + } + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + @Override + public int deleteAuthUser(SysUserRole userRole) + { + return userRoleMapper.deleteUserRoleInfo(userRole); + } + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + @Override + public int deleteAuthUsers(Long roleId, Long[] userIds) + { + return userRoleMapper.deleteUserRoleInfos(roleId, userIds); + } + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要授权的用户数据ID + * @return 结果 + */ + @Override + public int insertAuthUsers(Long roleId, Long[] userIds) + { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long userId : userIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + return userRoleMapper.batchUserRole(list); + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserOnlineServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserOnlineServiceImpl.java new file mode 100644 index 00000000..ab973a22 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserOnlineServiceImpl.java @@ -0,0 +1,89 @@ +package com.yanzhu.system.service.impl; + +import com.yanzhu.system.domain.SysUserOnline; +import org.springframework.stereotype.Service; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.system.api.model.LoginUser; +import com.yanzhu.system.service.ISysUserOnlineService; + +/** + * 在线用户 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysUserOnlineServiceImpl implements ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user) + { + if (StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + @Override + public SysUserOnline loginUserToUserOnline(LoginUser user) + { + if (StringUtils.isNull(user)) + { + return null; + } + SysUserOnline sysUserOnline = new SysUserOnline(); + sysUserOnline.setTokenId(user.getToken()); + sysUserOnline.setUserName(user.getUsername()); + sysUserOnline.setIpaddr(user.getIpaddr()); + sysUserOnline.setLoginTime(user.getLoginTime()); + return sysUserOnline; + } +} diff --git a/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserServiceImpl.java b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 00000000..54a430ae --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/java/com/yanzhu/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,545 @@ +package com.yanzhu.system.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Validator; + +import com.yanzhu.system.domain.SysPost; +import com.yanzhu.system.domain.SysUserPost; +import com.yanzhu.system.domain.SysUserRole; +import com.yanzhu.system.mapper.SysRoleMapper; +import com.yanzhu.system.mapper.SysUserMapper; +import com.yanzhu.system.mapper.SysUserPostMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import com.yanzhu.common.core.constant.UserConstants; +import com.yanzhu.common.core.exception.ServiceException; +import com.yanzhu.common.core.utils.SpringUtils; +import com.yanzhu.common.core.utils.StringUtils; +import com.yanzhu.common.core.utils.bean.BeanValidators; +import com.yanzhu.common.datascope.annotation.DataScope; +import com.yanzhu.common.security.utils.SecurityUtils; +import com.yanzhu.system.api.domain.SysRole; +import com.yanzhu.system.api.domain.SysUser; +import com.yanzhu.system.mapper.SysPostMapper; +import com.yanzhu.system.mapper.SysUserRoleMapper; +import com.yanzhu.system.service.ISysConfigService; +import com.yanzhu.system.service.ISysUserService; + +/** + * 用户 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysUserServiceImpl implements ISysUserService +{ + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); + + @Autowired + private SysUserMapper userMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + @Autowired + private ISysConfigService configService; + + @Autowired + protected Validator validator; + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) + { + return userMapper.selectUserList(user); + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectAllocatedList(SysUser user) + { + return userMapper.selectAllocatedList(user); + } + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUnallocatedList(SysUser user) + { + return userMapper.selectUnallocatedList(user); + } + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + @Override + public SysUser selectUserByUserName(String userName) + { + return userMapper.selectUserByUserName(userName); + } + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + @Override + public SysUser selectUserById(Long userId) + { + return userMapper.selectUserById(userId); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) + { + List list = roleMapper.selectRolesByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); + } + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) + { + List list = postMapper.selectPostsByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); + } + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean checkUserNameUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkUserNameUnique(user.getUserName()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public boolean checkPhoneUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public boolean checkEmailUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkEmailUnique(user.getEmail()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + @Override + public void checkUserAllowed(SysUser user) + { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) + { + throw new ServiceException("不允许操作超级管理员用户"); + } + } + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + @Override + public void checkUserDataScope(Long userId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysUser user = new SysUser(); + user.setUserId(userId); + List users = SpringUtils.getAopProxy(this).selectUserList(user); + if (StringUtils.isEmpty(users)) + { + throw new ServiceException("没有权限访问用户数据!"); + } + } + } + + /** + * 新增保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertUser(SysUser user) + { + // 新增用户信息 + int rows = userMapper.insertUser(user); + // 新增用户岗位关联 + insertUserPost(user); + // 新增用户与角色管理 + insertUserRole(user); + return rows; + } + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean registerUser(SysUser user) + { + return userMapper.insertUser(user) > 0; + } + + /** + * 修改保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateUser(SysUser user) + { + Long userId = user.getUserId(); + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 新增用户与角色管理 + insertUserRole(user); + // 删除用户与岗位关联 + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗位管理 + insertUserPost(user); + return userMapper.updateUser(user); + } + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void insertUserAuth(Long userId, Long[] roleIds) + { + userRoleMapper.deleteUserRoleByUserId(userId); + insertUserRole(userId, roleIds); + } + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserStatus(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserProfile(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + @Override + public boolean updateUserAvatar(String userName, String avatar) + { + return userMapper.updateUserAvatar(userName, avatar) > 0; + } + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int resetPwd(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + @Override + public int resetUserPwd(String userName, String password) + { + return userMapper.resetUserPwd(userName, password); + } + + /** + * 新增用户角色信息 + * + * @param user 用户对象 + */ + public void insertUserRole(SysUser user) + { + this.insertUserRole(user.getUserId(), user.getRoleIds()); + } + + /** + * 新增用户岗位信息 + * + * @param user 用户对象 + */ + public void insertUserPost(SysUser user) + { + Long[] posts = user.getPostIds(); + if (StringUtils.isNotEmpty(posts)) + { + // 新增用户与岗位管理 + List list = new ArrayList(); + for (Long postId : posts) + { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + userPostMapper.batchUserPost(list); + } + } + + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserRole(Long userId, Long[] roleIds) + { + if (StringUtils.isNotEmpty(roleIds)) + { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long roleId : roleIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + userRoleMapper.batchUserRole(list); + } + } + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteUserById(Long userId) + { + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 删除用户与岗位表 + userPostMapper.deleteUserPostByUserId(userId); + return userMapper.deleteUserById(userId); + } + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteUserByIds(Long[] userIds) + { + for (Long userId : userIds) + { + checkUserAllowed(new SysUser(userId)); + checkUserDataScope(userId); + } + // 删除用户与角色关联 + userRoleMapper.deleteUserRole(userIds); + // 删除用户与岗位关联 + userPostMapper.deleteUserPost(userIds); + return userMapper.deleteUserByIds(userIds); + } + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + @Override + public String importUser(List userList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(userList) || userList.size() == 0) + { + throw new ServiceException("导入用户数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + String password = configService.selectConfigByKey("sys.user.initPassword"); + for (SysUser user : userList) + { + try + { + // 验证是否存在这个用户 + SysUser u = userMapper.selectUserByUserName(user.getUserName()); + if (StringUtils.isNull(u)) + { + BeanValidators.validateWithException(validator, user); + user.setPassword(SecurityUtils.encryptPassword(password)); + user.setCreateBy(operName); + this.insertUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 导入成功"); + } + else if (isUpdateSupport) + { + BeanValidators.validateWithException(validator, user); + checkUserAllowed(user); + checkUserDataScope(user.getUserId()); + user.setUpdateBy(operName); + this.updateUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 更新成功"); + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "、账号 " + user.getUserName() + " 已存在"); + } + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + log.error(msg, e); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + +} diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-system/src/main/resources/banner.txt new file mode 100644 index 00000000..fbd45f53 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ + (_) | | + _ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___ +| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \ +| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | | +|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_| + __/ | __/ | + |___/ |___/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-system/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..5a0c2a85 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9201 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-system + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-system/src/main/resources/logback.xml new file mode 100644 index 00000000..7c49c8bf --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysAreaMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysAreaMapper.xml new file mode 100644 index 00000000..ef1e6ea2 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysAreaMapper.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + select id, parent_id, cname, ctype from sys_area + + + + + + + + insert into sys_area + + parent_id, + cname, + ctype, + + + #{parentId}, + #{cname}, + #{ctype}, + + + + + update sys_area + + parent_id = #{parentId}, + cname = #{cname}, + ctype = #{ctype}, + + where id = #{id} + + + + delete from sys_area where id = #{id} + + + + delete from sys_area where id in + + #{id} + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysConfigMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysConfigMapper.xml new file mode 100644 index 00000000..f241b6fe --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysConfigMapper.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark + from sys_config + + + + + + + and config_id = #{configId} + + + and config_key = #{configKey} + + + + + + + + + + + + + + insert into sys_config ( + config_name, + config_key, + config_value, + config_type, + create_by, + remark, + create_time + )values( + #{configName}, + #{configKey}, + #{configValue}, + #{configType}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_config + + config_name = #{configName}, + config_key = #{configKey}, + config_value = #{configValue}, + config_type = #{configType}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where config_id = #{configId} + + + + delete from sys_config where config_id = #{configId} + + + + delete from sys_config where config_id in + + #{configId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDeptMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDeptMapper.xml new file mode 100644 index 00000000..89ef5fe8 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time + from sys_dept d + + + + + + + + + + + + + + + + + + + + insert into sys_dept( + dept_id, + parent_id, + dept_name, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values( + #{deptId}, + #{parentId}, + #{deptName}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate() + ) + + + + update sys_dept + + parent_id = #{parentId}, + dept_name = #{deptName}, + ancestors = #{ancestors}, + order_num = #{orderNum}, + leader = #{leader}, + phone = #{phone}, + email = #{email}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where dept_id = #{deptId} + + + + update sys_dept set ancestors = + + when #{item.deptId} then #{item.ancestors} + + where dept_id in + + #{item.deptId} + + + + + update sys_dept set status = '0' where dept_id in + + #{deptId} + + + + + update sys_dept set del_flag = '2' where dept_id = #{deptId} + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictDataMapper.xml new file mode 100644 index 00000000..7e3b0829 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictDataMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark + from sys_dict_data + + + + + + + + + + + + + + delete from sys_dict_data where dict_code = #{dictCode} + + + + delete from sys_dict_data where dict_code in + + #{dictCode} + + + + + update sys_dict_data + + dict_sort = #{dictSort}, + dict_label = #{dictLabel}, + dict_value = #{dictValue}, + dict_type = #{dictType}, + css_class = #{cssClass}, + list_class = #{listClass}, + is_default = #{isDefault}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_code = #{dictCode} + + + + update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType} + + + + insert into sys_dict_data( + dict_sort, + dict_label, + dict_value, + dict_type, + css_class, + list_class, + is_default, + status, + remark, + create_by, + create_time + )values( + #{dictSort}, + #{dictLabel}, + #{dictValue}, + #{dictType}, + #{cssClass}, + #{listClass}, + #{isDefault}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictTypeMapper.xml new file mode 100644 index 00000000..da8025d5 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysDictTypeMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + select dict_id, dict_name, dict_type, status, create_by, create_time, remark + from sys_dict_type + + + + + + + + + + + + + + delete from sys_dict_type where dict_id = #{dictId} + + + + delete from sys_dict_type where dict_id in + + #{dictId} + + + + + update sys_dict_type + + dict_name = #{dictName}, + dict_type = #{dictType}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_id = #{dictId} + + + + insert into sys_dict_type( + dict_name, + dict_type, + status, + remark, + create_by, + create_time + )values( + #{dictName}, + #{dictType}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysLogininforMapper.xml new file mode 100644 index 00000000..b5b34729 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysLogininforMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + insert into sys_logininfor (user_name, status, ipaddr, msg, access_time) + values (#{userName}, #{status}, #{ipaddr}, #{msg}, sysdate()) + + + + + + delete from sys_logininfor where info_id in + + #{infoId} + + + + + truncate table sys_logininfor + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysMenuMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysMenuMapper.xml new file mode 100644 index 00000000..536ddaf9 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select menu_id, menu_name, parent_id, order_num, path, component, `query`, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time + from sys_menu + + + + + + + + + + + + + + + + + + + + + + + + + + update sys_menu + + menu_name = #{menuName}, + parent_id = #{parentId}, + order_num = #{orderNum}, + path = #{path}, + component = #{component}, + `query` = #{query}, + is_frame = #{isFrame}, + is_cache = #{isCache}, + menu_type = #{menuType}, + visible = #{visible}, + status = #{status}, + perms = #{perms}, + icon = #{icon}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where menu_id = #{menuId} + + + + insert into sys_menu( + menu_id, + parent_id, + menu_name, + order_num, + path, + component, + `query`, + is_frame, + is_cache, + menu_type, + visible, + status, + perms, + icon, + remark, + create_by, + create_time + )values( + #{menuId}, + #{parentId}, + #{menuName}, + #{orderNum}, + #{path}, + #{component}, + #{query}, + #{isFrame}, + #{isCache}, + #{menuType}, + #{visible}, + #{status}, + #{perms}, + #{icon}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_menu where menu_id = #{menuId} + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysNoticeMapper.xml new file mode 100644 index 00000000..061deebe --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysNoticeMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark + from sys_notice + + + + + + + + insert into sys_notice ( + notice_title, + notice_type, + notice_content, + status, + remark, + create_by, + create_time + )values( + #{noticeTitle}, + #{noticeType}, + #{noticeContent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_notice + + notice_title = #{noticeTitle}, + notice_type = #{noticeType}, + notice_content = #{noticeContent}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id in + + #{noticeId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysOperLogMapper.xml new file mode 100644 index 00000000..b3830cf0 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysOperLogMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_param, json_result, status, error_msg, oper_time, cost_time + from sys_oper_log + + + + insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_param, json_result, status, error_msg, cost_time, oper_time) + values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, #{costTime}, sysdate()) + + + + + + delete from sys_oper_log where oper_id in + + #{operId} + + + + + + + truncate table sys_oper_log + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysPostMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysPostMapper.xml new file mode 100644 index 00000000..faed89f0 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysPostMapper.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark + from sys_post + + + + + + + + + + + + + + + + + + update sys_post + + post_code = #{postCode}, + post_name = #{postName}, + post_sort = #{postSort}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where post_id = #{postId} + + + + insert into sys_post( + post_id, + post_code, + post_name, + post_sort, + status, + remark, + create_by, + create_time + )values( + #{postId}, + #{postCode}, + #{postName}, + #{postSort}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_post where post_id = #{postId} + + + + delete from sys_post where post_id in + + #{postId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml new file mode 100644 index 00000000..b31d73cd --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_role_dept where role_id=#{roleId} + + + + + + delete from sys_role_dept where role_id in + + #{roleId} + + + + + insert into sys_role_dept(role_id, dept_id) values + + (#{item.roleId},#{item.deptId}) + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMapper.xml new file mode 100644 index 00000000..f2304b03 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly, + r.status, r.del_flag, r.create_time, r.remark + from sys_role r + left join sys_user_role ur on ur.role_id = r.role_id + left join sys_user u on u.user_id = ur.user_id + left join sys_dept d on u.dept_id = d.dept_id + + + + + + + + + + + + + + + + + + + + insert into sys_role( + role_id, + role_name, + role_key, + role_sort, + data_scope, + menu_check_strictly, + dept_check_strictly, + status, + remark, + create_by, + create_time + )values( + #{roleId}, + #{roleName}, + #{roleKey}, + #{roleSort}, + #{dataScope}, + #{menuCheckStrictly}, + #{deptCheckStrictly}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_role + + role_name = #{roleName}, + role_key = #{roleKey}, + role_sort = #{roleSort}, + data_scope = #{dataScope}, + menu_check_strictly = #{menuCheckStrictly}, + dept_check_strictly = #{deptCheckStrictly}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id in + + #{roleId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml new file mode 100644 index 00000000..b48fe696 --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + delete from sys_role_menu where role_id=#{roleId} + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + insert into sys_role_menu(role_id, menu_id) values + + (#{item.roleId},#{item.menuId}) + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserMapper.xml new file mode 100644 index 00000000..61af0edb --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, + d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, + r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status + from sys_user u + left join sys_dept d on u.dept_id = d.dept_id + left join sys_user_role ur on u.user_id = ur.user_id + left join sys_role r on r.role_id = ur.role_id + + + + + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where user_id = #{userId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + update sys_user set avatar = #{avatar} where user_name = #{userName} + + + + update sys_user set password = #{password} where user_name = #{userName} + + + + update sys_user set del_flag = '2' where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserPostMapper.xml new file mode 100644 index 00000000..e8ca65bb --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserPostMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_user_post where user_id=#{userId} + + + + + + delete from sys_user_post where user_id in + + #{userId} + + + + + insert into sys_user_post(user_id, post_id) values + + (#{item.userId},#{item.postId}) + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserRoleMapper.xml new file mode 100644 index 00000000..16b0a2aa --- /dev/null +++ b/yanzhu-modules/yanzhu-system/src/main/resources/mapper/system/SysUserRoleMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + delete from sys_user_role where user_id=#{userId} + + + + + + delete from sys_user_role where user_id in + + #{userId} + + + + + insert into sys_user_role(user_id, role_id) values + + (#{item.userId},#{item.roleId}) + + + + + delete from sys_user_role where user_id=#{userId} and role_id=#{roleId} + + + + delete from sys_user_role where role_id=#{roleId} and user_id in + + #{userId} + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-wechat/pom.xml b/yanzhu-modules/yanzhu-wechat/pom.xml new file mode 100644 index 00000000..8d047373 --- /dev/null +++ b/yanzhu-modules/yanzhu-wechat/pom.xml @@ -0,0 +1,154 @@ + + + + yanzhu + com.yanzhu + 3.6.2 + ../../pom.xml + + 4.0.0 + + yanzhu-modules-wechat + + + 17 + 17 + + + + yanzhu-modules-wechat微信模块 + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + org.apache.velocity + velocity-engine-core + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + org.projectlombok + lombok + provided + + + + + com.yanzhu + yanzhu-common-mapper + 3.6.2 + compile + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/RuoYiWeChatApplication.java b/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/RuoYiWeChatApplication.java new file mode 100644 index 00000000..b2ca6503 --- /dev/null +++ b/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/RuoYiWeChatApplication.java @@ -0,0 +1,34 @@ +package com.yanzhu.wechat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 代码生成 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class RuoYiWeChatApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiWeChatApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 微信模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/controller/init b/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/controller/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/impl/init b/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/impl/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/init b/yanzhu-modules/yanzhu-wechat/src/main/java/com/yanzhu/wechat/service/init new file mode 100644 index 00000000..e69de29b diff --git a/yanzhu-modules/yanzhu-wechat/src/main/resources/banner.txt b/yanzhu-modules/yanzhu-wechat/src/main/resources/banner.txt new file mode 100644 index 00000000..05f528cc --- /dev/null +++ b/yanzhu-modules/yanzhu-wechat/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ + (_) + _ __ _ _ ___ _ _ _ ______ __ _ ___ _ __ +| '__|| | | | / _ \ | | | || ||______| / _` | / _ \| '_ \ +| | | |_| || (_) || |_| || | | (_| || __/| | | | +|_| \__,_| \___/ \__, ||_| \__, | \___||_| |_| + __/ | __/ | + |___/ |___/ \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-wechat/src/main/resources/bootstrap.yml b/yanzhu-modules/yanzhu-wechat/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..b017cda4 --- /dev/null +++ b/yanzhu-modules/yanzhu-wechat/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9206 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-wechat + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-modules/yanzhu-wechat/src/main/resources/logback.xml b/yanzhu-modules/yanzhu-wechat/src/main/resources/logback.xml new file mode 100644 index 00000000..ec8cfeba --- /dev/null +++ b/yanzhu-modules/yanzhu-wechat/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-monitor/pom.xml b/yanzhu-monitor/pom.xml new file mode 100644 index 00000000..ad996412 --- /dev/null +++ b/yanzhu-monitor/pom.xml @@ -0,0 +1,119 @@ + + + yanzhu + com.yanzhu + 3.6.2 + + 4.0.0 + + yanzhu-monitor + + + yanzhu-monitor监控中心 + + + + + + + de.codecentric + spring-boot-admin-starter-server + ${spring-boot-admin.version} + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/RuoYiMonitorApplication.java b/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/RuoYiMonitorApplication.java new file mode 100644 index 00000000..c05813a7 --- /dev/null +++ b/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/RuoYiMonitorApplication.java @@ -0,0 +1,30 @@ +package com.yanzhu.modules.monitor; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import de.codecentric.boot.admin.server.config.EnableAdminServer; + +/** + * 监控中心 + * + * @author ruoyi + */ +@EnableAdminServer +@SpringBootApplication +public class RuoYiMonitorApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiMonitorApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 监控中心启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/config/WebSecurityConfigurer.java b/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/config/WebSecurityConfigurer.java new file mode 100644 index 00000000..0ee04ddf --- /dev/null +++ b/yanzhu-monitor/src/main/java/com/yanzhu/modules/monitor/config/WebSecurityConfigurer.java @@ -0,0 +1,51 @@ +package com.yanzhu.modules.monitor.config; + +import de.codecentric.boot.admin.server.config.AdminServerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; + +/** + * 监控权限配置 + * + * @author ruoyi + */ +@EnableWebSecurity +public class WebSecurityConfigurer +{ + private final String adminContextPath; + + public WebSecurityConfigurer(AdminServerProperties adminServerProperties) + { + this.adminContextPath = adminServerProperties.getContextPath(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception + { + SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); + successHandler.setTargetUrlParameter("redirectTo"); + successHandler.setDefaultTargetUrl(adminContextPath + "/"); + + return httpSecurity + .headers().frameOptions().disable() + .and().authorizeRequests() + .antMatchers(adminContextPath + "/assets/**" + , adminContextPath + "/login" + , adminContextPath + "/actuator/**" + , adminContextPath + "/instances/**" + ).permitAll() + .anyRequest().authenticated() + .and() + .formLogin().loginPage(adminContextPath + "/login") + .successHandler(successHandler).and() + .logout().logoutUrl(adminContextPath + "/logout") + .and() + .httpBasic().and() + .csrf() + .disable() + .build(); + } +} diff --git a/yanzhu-monitor/src/main/resources/banner.txt b/yanzhu-monitor/src/main/resources/banner.txt new file mode 100644 index 00000000..ecaf8a4d --- /dev/null +++ b/yanzhu-monitor/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ _ + (_) (_)| | + _ __ _ _ ___ _ _ _ ______ _ __ ___ ___ _ __ _ | |_ ___ _ __ +| '__|| | | | / _ \ | | | || ||______|| '_ ` _ \ / _ \ | '_ \ | || __| / _ \ | '__| +| | | |_| || (_) || |_| || | | | | | | || (_) || | | || || |_ | (_) || | +|_| \__,_| \___/ \__, ||_| |_| |_| |_| \___/ |_| |_||_| \__| \___/ |_| + __/ | + |___/ \ No newline at end of file diff --git a/yanzhu-monitor/src/main/resources/bootstrap.yml b/yanzhu-monitor/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..cf2703c3 --- /dev/null +++ b/yanzhu-monitor/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9100 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-monitor + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/yanzhu-monitor/src/main/resources/logback.xml b/yanzhu-monitor/src/main/resources/logback.xml new file mode 100644 index 00000000..9d8db3c8 --- /dev/null +++ b/yanzhu-monitor/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yanzhu-rocketmq/pom.xml b/yanzhu-rocketmq/pom.xml new file mode 100644 index 00000000..d7b097f3 --- /dev/null +++ b/yanzhu-rocketmq/pom.xml @@ -0,0 +1,144 @@ + + + + yanzhu + com.yanzhu + 3.6.2 + + 4.0.0 + + yanzhu-rocketmq + + + + + org.apache.rocketmq + rocketmq-client + 4.9.0 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + com.alibaba.nacos + nacos-client + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + mysql + mysql-connector-java + + + + + com.yanzhu + yanzhu-common-log + + + + + com.yanzhu + yanzhu-common-swagger + + + com.yanzhu + yanzhu-common-security + + + org.projectlombok + lombok + + + + + org.yaml + snakeyaml + 1.28 + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + com.spotify + docker-maven-plugin + 1.2.0 + + + ${project.build.finalName} + latest + + openjdk:latest + + ["java", "-jar", "/${project.build.finalName}.jar"] + + + ${configuration.docker-one-Host} + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + build-image + package + + build + + + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/RocketMQApplication.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/RocketMQApplication.java new file mode 100644 index 00000000..5d57da70 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/RocketMQApplication.java @@ -0,0 +1,27 @@ +package com.yanzhu.rocketmq; + +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * 平台管理模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +@EnableAsync +public class RocketMQApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RocketMQApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ RocketMQ模块启动成功 ლ(´ڡ`ლ)゙"); + } +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ConsumerConfig.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ConsumerConfig.java new file mode 100644 index 00000000..36f8027e --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ConsumerConfig.java @@ -0,0 +1,74 @@ +package com.yanzhu.rocketmq.config; + +import com.yanzhu.rocketmq.enums.MessageTopic; +import com.yanzhu.rocketmq.model.ConsumerMode; +import com.yanzhu.rocketmq.consumer.RocketMsgListener; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +/** + * 消费者配置 + */ +@RefreshScope +@Configuration +@Slf4j +public class ConsumerConfig { + + @Autowired + private ConsumerMode consumerMode; + + @Bean + public DefaultMQPushConsumer getRocketMQConsumer() { + //构建客户端连接 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getGroupName()); + // + consumer.setNamesrvAddr(consumerMode.getNamesrvAddr()); + consumer.setConsumeThreadMin(consumerMode.getConsumeThreadMin()); + consumer.setConsumeThreadMax(consumerMode.getConsumeThreadMax()); + consumer.registerMessageListener(new RocketMsgListener()); + /** + * 1. CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费 + * 2. CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费 + * 3. CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费 + * 以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始 + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + /** + * CLUSTERING (集群模式) :默认模式,同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消息加起来才是所 + * 订阅topic整体,从而达到负载均衡的目的 + * BROADCASTING (广播模式) :同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息,也就是一个消费会被多次分发,被多个consumer消费。 + * 需要注意的是,在广播模式下,每个Consumer都会独立地处理相同的消息副本。这可能会导致一些潜在的问题,例如消息重复处理或者资源浪费。因此,在使用广播模式时,请确保消息的处理逻辑是幂等的,并仔细考虑系统资源的消耗。 + */ + // consumer.setMessageModel(MessageModel.BROADCASTING); + + consumer.setVipChannelEnabled(false); + consumer.setConsumeMessageBatchMaxSize(consumerMode.getConsumeMessageBatchMaxSize()); + try { + /** + * 订阅topic,可以对指定消息进行过滤,例如:"TopicTest","tagl||tag2||tag3",*或null表示topic所有消息 + * 由于官方并没有给直接订阅全部消息示例 所以使用list列表循环订阅所有topic + */ + // 获取所有topic列表 + MessageTopic messageTopic = new MessageTopic(); + List allTopics = messageTopic.RocketMQTopicList(); + //订阅所有topic + for (String topic : allTopics) { + consumer.subscribe(topic,"*"); + } + consumer.start(); + log.info("消费者初始化成功:{}", consumer); + } catch (MQClientException e) { + e.printStackTrace(); + log.error("消费者初始化失败:{}",e.getMessage()); + } + return consumer; + } +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ProducerConfig.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ProducerConfig.java new file mode 100644 index 00000000..e01ac191 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/config/ProducerConfig.java @@ -0,0 +1,56 @@ +package com.yanzhu.rocketmq.config; + +import com.yanzhu.rocketmq.model.ProducerMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * mq搭建地址连接 + * 生产者初者连接信息 具体看nacos配置 + */ +@Configuration +@Slf4j +public class ProducerConfig { + + /** + * 远程调用连接信息 + */ + public static DefaultMQProducer producer; + + /** + * 连接客户端信息配置 具体看nacos配置 + */ + @Autowired + private ProducerMode producerMode; + + @Bean + public DefaultMQProducer getRocketMQProducer() { + producer = new DefaultMQProducer(producerMode.getGroupName()); + producer.setNamesrvAddr(producerMode.getNamesrvAddr()); + //如果需要同一个jvm中不同的producer往不同的mq集群发送消息,需要设置不同的instanceName + if(producerMode.getMaxMessageSize()!=null){ + producer.setMaxMessageSize(producerMode.getMaxMessageSize()); + } + if(producerMode.getSendMsgTimeout()!=null){ + producer.setSendMsgTimeout(producerMode.getSendMsgTimeout()); + } + //如果发送消息失败,设置重试次数,默认为2次 + if(producerMode.getRetryTimesWhenSendFailed()!=null){ + producer.setRetryTimesWhenSendFailed(producerMode.getRetryTimesWhenSendFailed()); + } + producer.setVipChannelEnabled(false); + try { + producer.start(); + log.info("生产者初始化成功:{}",producer.toString()); + } catch (MQClientException e) { + log.error("生产者初始化失败:{}",e.getMessage()); + } + return producer; + } + +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgListener.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgListener.java new file mode 100644 index 00000000..35b4bdc1 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgListener.java @@ -0,0 +1,86 @@ +package com.yanzhu.rocketmq.consumer; + +import com.yanzhu.rocketmq.enums.MessageCodeEnum; +import com.yanzhu.rocketmq.producer.ConsumeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.io.UnsupportedEncodingException; +import java.util.List; + +/** + * 消息监听 + */ +@Slf4j +@Component +public class RocketMsgListener implements MessageListenerConcurrently { + + /** + * 消费消息 + * @param list msgs.size() >= 1 + * DefaultMQPushConsumer.consumeMessageBatchMaxSize=1,you can modify here + * 这里只设置为1,当设置为多个时,list中只要有一条消息消费失败,就会整体重试 + * @param consumeConcurrentlyContext 上下文信息 + * @return 消费状态 成功(CONSUME_SUCCESS)或者 重试 (RECONSUME_LATER) + */ + @Override + public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) { + try{ + //消息不等于空情况 + if (!CollectionUtils.isEmpty(list)) { + //获取topic + for (MessageExt messageExt : list) { + // 解析消息内容 + String body = new String(messageExt.getBody()); + log.info("接受到的消息为:{}", body); + String tags = messageExt.getTags(); + String topic = messageExt.getTopic(); + String msgId = messageExt.getMsgId(); + String keys = messageExt.getKeys(); + int reConsume = messageExt.getReconsumeTimes(); + // 消息已经重试了3次,如果不需要再次消费,则返回成功 + if (reConsume == 3) { + // TODO 补偿信息 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//根据业务返回是否正常 + } + // 根据不同的topic处理不同的业务 这里以订单消息为例子 + if (MessageCodeEnum.ORDER_MESSAGE_TOPIC.getCode().equals(topic)) { + if (MessageCodeEnum.ORDER_TIMEOUT_TAG.getCode().equals(tags)) { + //处理你的业务 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//业务处理成功 + } else { + log.info("未匹配到Tag【{}】" + tags); + } + } + } + } + // 消息消费失败 + //broker会根据设置的messageDelayLevel发起重试,默认16次 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } catch (Exception e) { + // 调用 handleException 方法处理异常并返回处理结果 + return handleException(e); + } + } + + /** + * 异常处理 + * + * @param e 捕获的异常 + * @return 消息消费结果 + */ + private static ConsumeConcurrentlyStatus handleException(final Exception e) { + Class exceptionClass = e.getClass(); + if (exceptionClass.equals(UnsupportedEncodingException.class)) { + log.error(e.getMessage()); + } else if (exceptionClass.equals(ConsumeException.class)) { + log.error(e.getMessage()); + } + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgTransactionListenerImpl.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgTransactionListenerImpl.java new file mode 100644 index 00000000..189d6a00 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/consumer/RocketMsgTransactionListenerImpl.java @@ -0,0 +1,30 @@ +package com.yanzhu.rocketmq.consumer; + +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; + +/** + * 事物消息监听 + */ +public class RocketMsgTransactionListenerImpl implements TransactionListener { + + @Override + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { + // 在这里执行本地事务,比如数据库操作等 + // 如果本地事务执行成功,返回 COMMIT_MESSAGE + // 如果本地事务执行失败,返回 ROLLBACK_MESSAGE + // 如果本地事务执行中,可以返回 UNKNOW,RocketMQ 将会检查事务状态,并根据状态处理消息 + return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态 + } + + @Override + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + // 检查本地事务状态,如果本地事务执行成功,返回 COMMIT_MESSAGE + // 如果本地事务执行失败,返回 ROLLBACK_MESSAGE + // 如果本地事务仍在执行中,返回 UNKNOW,RocketMQ 将会继续检查事务状态 + return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态 + } + +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/controller/RocketMqController.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/controller/RocketMqController.java new file mode 100644 index 00000000..e14c09cd --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/controller/RocketMqController.java @@ -0,0 +1,137 @@ +package com.yanzhu.rocketmq.controller; + + +import com.yanzhu.rocketmq.producer.MessageProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 消息测试类Controller + */ +@RestController +@RequestMapping("/api/rocketMessage") +public class RocketMqController { + + + + /** + * 发送同步消息 + */ + @PostMapping("/sendSynchronizeMessage") + private Map sendSynchronizeMessage(){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 + SendResult sendResult = messageProducer.sendSynchronizeMessage("order-message","order_message_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + + /** + * 发送单向消息 + */ + @PostMapping("/sendOnewayMessage") + private Map sendOnewayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + messageProducer.sendOnewayMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("msg","发送成功"); + result.put("code",200); + return result; + } + + + /** + * 批量发送消息 + */ + @PostMapping("/sendBatchMessage") + private Map sendBatchMessage(){ + // 根据实际需求创建消息列表并返回 + List messages = new ArrayList<>(); + // 添加消息到列表 + messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes())); + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendBatchMessage(messages); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送事物消息 + */ + @PostMapping("/sendThingMessage") + private Map sendThingMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendThingMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送有序的消息 + */ + @PostMapping("/sendOrderlyMessage") + private Map sendOrderlyMessage(){ + // 根据实际需求创建消息列表并返回 + List messages = new ArrayList<>(); + // 添加消息到列表 + messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes())); + Integer messageQueueNumber = 3; + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendOrderlyMessage(messages,messageQueueNumber); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + /** + * 发送延迟消息 + */ + @PostMapping("/sendDelayMessage") + private Map sendDelayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendDelayMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送异步的消息 + */ + @PostMapping("/sendAsyncProducerMessage") + private Map sendAsyncProducerMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendAsyncProducerMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageCodeEnum.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageCodeEnum.java new file mode 100644 index 00000000..ba40789c --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageCodeEnum.java @@ -0,0 +1,55 @@ +package com.yanzhu.rocketmq.enums; + + +import lombok.Getter; + +/** + * 用于传递topic和 tag + * 也用于接收消息后判断不同的消息处理不同的业务 + */ +@Getter +public enum MessageCodeEnum { + + /** + * 系统消息 + */ + NOTE_MESSAGE_TOPIC("system-message","系统消息服务模块topic名称"), + /** + * 用户消息 + */ + USER_MESSAGE_TOPIC("user-message","用户消息服务模块topic名称"), + + /** + * 订单消息 + */ + ORDER_MESSAGE_TOPIC("order-message","订单消息服务模块topic名称"), + + /** + * 用户消息tag + */ + USER_MESSAGE_TAG("user_message_tag","用户消息推送"), + + /** + * 系统消息tag + */ + NOTE_MESSAGE_TAG("system_message_tag","系统消息推送"), + + /** + * 订单消息 + */ + ORDER_MESSAGE_TAG("order_message_tag","订单消息推送"), + + /** + * 订单处理编号 + */ + ORDER_TIMEOUT_TAG("order_timeout_tag","订单超时处理"); + + private final String code; + private final String msg; + + MessageCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageTopic.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageTopic.java new file mode 100644 index 00000000..0c942649 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/enums/MessageTopic.java @@ -0,0 +1,24 @@ +package com.yanzhu.rocketmq.enums; + + +import java.util.ArrayList; +import java.util.List; + +/** + * 定义topic列表 + */ +public class MessageTopic { + + //在这里添加topic 用于批量订阅 + public List RocketMQTopicList(){ + List getTopicLists=new ArrayList<>(); + //系统消息 + getTopicLists.add("system-message"); + //用户消息 + getTopicLists.add("user-message"); + //订单消息 + getTopicLists.add("order-message"); + return getTopicLists; + } + +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ConsumerMode.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ConsumerMode.java new file mode 100644 index 00000000..baeada4a --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ConsumerMode.java @@ -0,0 +1,26 @@ +package com.yanzhu.rocketmq.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +/** + * 消费者初始化 + * 消费者连接信息 具体看nacos配置 + */ +@Data +@Configuration +@Component +public class ConsumerMode { + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.conumer.groupName}") + private String groupName ; + @Value("${suning.rocketmq.conumer.consumeThreadMin}") + private int consumeThreadMin; + @Value("${suning.rocketmq.conumer.consumeThreadMax}") + private int consumeThreadMax; + @Value("${suning.rocketmq.conumer.consumeMessageBatchMaxSize}") + private int consumeMessageBatchMaxSize; +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ProducerMode.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ProducerMode.java new file mode 100644 index 00000000..c45a9a6f --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/model/ProducerMode.java @@ -0,0 +1,25 @@ +package com.yanzhu.rocketmq.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 生产者初始化 + */ +@RefreshScope +@Data +@Configuration +public class ProducerMode { + @Value("${suning.rocketmq.producer.groupName}") + private String groupName; + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.producer.maxMessageSize}") + private Integer maxMessageSize; + @Value("${suning.rocketmq.producer.sendMsgTimeout}") + private Integer sendMsgTimeout; + @Value("${suning.rocketmq.producer.retryTimesWhenSendFailed}") + private Integer retryTimesWhenSendFailed; +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/ConsumeException.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/ConsumeException.java new file mode 100644 index 00000000..16608a3a --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/ConsumeException.java @@ -0,0 +1,23 @@ +package com.yanzhu.rocketmq.producer; + +/** + * @author 影子 + * 用于捕捉异常非受检异常(unchecked exception) + * RuntimeException 和其子类的异常在编译时不需要进行强制性的异常处理,可以选择在运行时进行捕获和处理 + * 可选择使用 + */ +public class ConsumeException extends RuntimeException{ + private static final long serialVersionUID = 4093867789628938836L; + + public ConsumeException(String message) { + super(message); + } + + public ConsumeException(Throwable cause) { + super(cause); + } + + public ConsumeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/MessageProducer.java b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/MessageProducer.java new file mode 100644 index 00000000..fd2a6dd6 --- /dev/null +++ b/yanzhu-rocketmq/src/main/java/com/yanzhu/rocketmq/producer/MessageProducer.java @@ -0,0 +1,223 @@ +package com.yanzhu.rocketmq.producer; + +import com.alibaba.fastjson.JSON; +import com.yanzhu.rocketmq.consumer.RocketMsgTransactionListenerImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.producer.TransactionSendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import static com.yanzhu.rocketmq.config.ProducerConfig.producer; + +/** + * 消息发送 + */ +@Slf4j +public class MessageProducer { + + + /** + * 同步发送消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 通过调用 send() 方法发送消息,阻塞等待服务器响应。 + */ + public SendResult sendSynchronizeMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + SendResult result = producer.send(msg); + return result; + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException | InterruptedException | RemotingException | MQBrokerException e) { + log.error("消息发送失败! body:{}",body); + } + return null; + } + + /** + * 单向发送消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 单向发送:通过调用 sendOneway() 方法发送消息,不关心发送结果,适用于对可靠性要求不高的场景。 + */ + public void sendOnewayMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + producer.sendOneway(msg); + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException | InterruptedException | RemotingException e) { + log.error("消息发送失败! body:{}",body); + } + } + + + /** + * 批量发送消息 + * @param messages 消息列表 + * 批量发送:通过调用 send() 方法并传入多条消息,实现批量发送消息。 + */ + public SendResult sendBatchMessage(List messages){ + String body = messages.toString(); + try { + System.out.println("生产者发送消息:"+ messages); + // 发送批量消息 + SendResult sendResult = producer.send(messages); + return sendResult; + } catch (MQClientException | InterruptedException | RemotingException e) { + log.error("消息发送失败! body:{}",body); + } catch (MQBrokerException e) { + throw new RuntimeException(e); + } + return null; + } + + + /** + * 事务消息发送 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 事务消息发送:通过使用事务监听器实现本地事务执行和消息发送的一致性。 + */ + public SendResult sendThingMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + // 实例化事务生产者 + TransactionMQProducer transactionMQProducer = new TransactionMQProducer(producer.getProducerGroup()); + transactionMQProducer.setNamesrvAddr(producer.getNamesrvAddr()); + // 设置事务监听器 + transactionMQProducer.setTransactionListener(new RocketMsgTransactionListenerImpl()); + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + // 发送事务消息 + TransactionSendResult sendResult = transactionMQProducer.sendMessageInTransaction(msg, null); + return sendResult; + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException e) { + log.error("消息发送失败! body:{}",body); + } + return null; + } + + + /** + * 发送有序的消息 + * @param messagesList Message集合 + * @param messageQueueNumber 消息队列数量,根据实际情况设定 + * 顺序发送: messageQueueNumber 表示消息的业务标识,可以根据具体需求进行设置来保证消息按顺序发送。 + */ + public SendResult sendOrderlyMessage(List messagesList, Integer messageQueueNumber) { + SendResult result = null; + for (Message message : messagesList) { + try { + result = producer.send(message, (list, msg, arg) -> { + Integer queueNumber = (Integer) arg; + //int queueIndex = queueNumber % list.size(); + return list.get(queueNumber); + }, messageQueueNumber);//根据编号取模,选择消息队列 + } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) { + log.error("发送有序消息失败"); + return result; + } + } + return result; + } + + /** + * 发送延迟消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 延迟发送:通过设置延迟级别来实现延迟发送消息。 + */ + public SendResult sendDelayMessage(String topic, String tag, String key, String value) + { + SendResult result = null; + try + { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + //设置消息延迟级别,我这里设置5,对应就是延时一分钟 + // "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" + msg.setDelayTimeLevel(4); + // 发送消息到一个Broker + result = producer.send(msg); + // 通过sendResult返回消息是否成功送达 + log.info("发送延迟消息结果:======sendResult:{}", result); + DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + log.info("发送时间:{}", format.format(new Date())); + return result; + } + catch (Exception e) + { + e.printStackTrace(); + log.error("延迟消息队列推送消息异常:{},推送内容:{}", e.getMessage(), result); + } + return result; + } + /** + * 发送异步的消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 通过调用 send() 方法,并传入一个 SendCallback 对象,在发送消息的同时可以继续处理其他逻辑,消息发送结果通过回调函数通知。 + */ + public SendResult sendAsyncProducerMessage(String topic, String tag, String key, String value){ + + try { + //创建一个消息实例,指定主题、标签和消息体。 + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + producer.send(msg,new SendCallback() { + // 异步回调的处理 + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d 异步发送消息成功 %s %n", msg, sendResult.getMsgId()); + } + @Override + public void onException(Throwable e) { + System.out.printf("%-10d 异步发送消息失败 %s %n", msg, e); + e.printStackTrace(); + } + }); + } catch (MQClientException e) { + e.printStackTrace(); + } catch (RemotingException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + return null; + } + +} diff --git a/yanzhu-rocketmq/src/main/resources/bootstrap.yml b/yanzhu-rocketmq/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..0b11c9e1 --- /dev/null +++ b/yanzhu-rocketmq/src/main/resources/bootstrap.yml @@ -0,0 +1,35 @@ +# Tomcat +server: + port: 9207 + +# Spring +spring: + application: + # 应用名称 + name: yanzhu-rocketmq + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: @discovery.server-addr@ + config: + # 配置中心地址 + server-addr: @discovery.server-addr@ + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + + redisson: + singleServerConfig: + address: redis://localhost:6379 +logging: + level: + com.ruoyi.app.mapper: DEBUG + + + diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/RocketMQApplication.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/RocketMQApplication.java new file mode 100644 index 00000000..f9036d2b --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/RocketMQApplication.java @@ -0,0 +1,27 @@ +package com.yanzhu.testrocketmq; + +import com.yanzhu.common.security.annotation.EnableCustomConfig; +import com.yanzhu.common.security.annotation.EnableRyFeignClients; +import com.yanzhu.common.swagger.annotation.EnableCustomSwagger2; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * 平台管理模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +@EnableAsync +public class RocketMQApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RocketMQApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ RocketMQ模块启动成功 ლ(´ڡ`ლ)゙"); + } +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ConsumerConfig.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ConsumerConfig.java new file mode 100644 index 00000000..8929aee7 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ConsumerConfig.java @@ -0,0 +1,64 @@ +package com.yanzhu.testrocketmq.config; + +import com.yanzhu.testrocketmq.consumer.RocketMsgListener; +import com.yanzhu.testrocketmq.enums.MessageCodeEnum; +import com.yanzhu.testrocketmq.model.ConsumerMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 消费者配置 + */ +@RefreshScope +@Configuration +@Slf4j +public class ConsumerConfig { + @Autowired + private ConsumerMode consumerMode; + + @Bean + public DefaultMQPushConsumer getRocketMQConsumer() throws MQClientException { +// ConsumerMode consumerMode = new ConsumerMode(); + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getGroupName()); + consumer.setNamesrvAddr(consumerMode.getNamesrvAddr()); + consumer.setConsumeThreadMin(consumerMode.getConsumeThreadMin()); + consumer.setConsumeThreadMax(consumerMode.getConsumeThreadMax()); + consumer.registerMessageListener(new RocketMsgListener()); + /** + * 1. CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费 + * 2. CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费 + * 3. CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费 + * 以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始 + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + /** + * CLUSTERING (集群模式) :默认模式,同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消息加起来才是所 + * 订阅topic整体,从而达到负载均衡的目的 + * BROADCASTING (广播模式) :同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息,也就是一个消费会被多次分发,被多个consumer消费。 + * + */ + // consumer.setMessageModel(MessageModel.BROADCASTING); + + consumer.setVipChannelEnabled(false); + consumer.setConsumeMessageBatchMaxSize(consumerMode.getConsumeMessageBatchMaxSize()); + try { + /** + * 订阅topic,可以对指定消息进行过滤,例如:"TopicTest","tagl||tag2||tag3",*或null表示topic所有消息 + */ + consumer.subscribe(MessageCodeEnum.ORDER_MESSAGE.getCode(),"*"); + consumer.subscribe(MessageCodeEnum.USER_MESSAGE.getCode(),"*"); + consumer.start(); + log.info("消费者初始化成功:{}", consumer.toString()); + } catch (MQClientException e) { + e.printStackTrace(); + log.error("消费者初始化失败:{}",e.getMessage()); + } + return consumer; + } +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/MessageConfig.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/MessageConfig.java new file mode 100644 index 00000000..3b4deee1 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/MessageConfig.java @@ -0,0 +1,27 @@ +package com.yanzhu.testrocketmq.config; + +/** + * @author yz + */ +public class MessageConfig { + private Class messageClass; + private boolean orderlyMessage; + + public Class getMessageClass() { + return messageClass; + } + + public void setMessageClass(Class messageClass) { + this.messageClass = messageClass; + } + + public boolean isOrderlyMessage() { + return orderlyMessage; + } + + public void setOrderlyMessage(boolean orderlyMessage) { + this.orderlyMessage = orderlyMessage; + } + + +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ProducerConfig.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ProducerConfig.java new file mode 100644 index 00000000..e85bf728 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/config/ProducerConfig.java @@ -0,0 +1,48 @@ +package com.yanzhu.testrocketmq.config; + +import com.yanzhu.testrocketmq.model.ProducerMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +@Slf4j +public class ProducerConfig { + + public static DefaultMQProducer producer; + + @Autowired + private ProducerMode producerMode; + + + + @Bean + public DefaultMQProducer getRocketMQProducer() { + producer = new DefaultMQProducer(producerMode.getGroupName()); + producer.setNamesrvAddr(producerMode.getNamesrvAddr()); + //如果需要同一个jvm中不同的producer往不同的mq集群发送消息,需要设置不同的instanceName + if(producerMode.getMaxMessageSize()!=null){ + producer.setMaxMessageSize(producerMode.getMaxMessageSize()); + } + if(producerMode.getSendMsgTimeout()!=null){ + producer.setSendMsgTimeout(producerMode.getSendMsgTimeout()); + } + //如果发送消息失败,设置重试次数,默认为2次 + if(producerMode.getRetryTimesWhenSendFailed()!=null){ + producer.setRetryTimesWhenSendFailed(producerMode.getRetryTimesWhenSendFailed()); + } + producer.setVipChannelEnabled(false); + try { + producer.start(); + log.info("生产者初始化成功:{}",producer.toString()); + } catch (MQClientException e) { + log.error("生产者初始化失败:{}",e.getMessage()); + } + return producer; + } + +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/consumer/RocketMsgListener.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/consumer/RocketMsgListener.java new file mode 100644 index 00000000..32409797 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/consumer/RocketMsgListener.java @@ -0,0 +1,100 @@ +package com.yanzhu.testrocketmq.consumer; + +import com.yanzhu.testrocketmq.enums.MessageCodeEnum; +import com.yanzhu.testrocketmq.producer.ConsumeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * 消息监听 + */ +@Slf4j +@Component +public class RocketMsgListener implements MessageListenerConcurrently { + + /** + * 消费消息 + * + * @param list msgs.size() >= 1 + * DefaultMQPushConsumer.consumeMessageBatchMaxSize=1,you can modify here + * 这里只设置为1,当设置为多个时,list中只要有一条消息消费失败,就会整体重试 + * @param consumeConcurrentlyContext 上下文信息 + * @return 消费状态 成功(CONSUME_SUCCESS)或者 重试 (RECONSUME_LATER) + */ + @Override + public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) { + + if (!CollectionUtils.isEmpty(list)) { + for (MessageExt messageExt : list) { + // 消息内容 + String body = new String(messageExt.getBody()); + log.info("接受到的消息为:{}", body); + String tags = messageExt.getTags(); + String topic = messageExt.getTopic(); + String msgId = messageExt.getMsgId(); + String keys = messageExt.getKeys(); + int reConsume = messageExt.getReconsumeTimes(); + // 消息已经重试了3次,如果不需要再次消费,则返回成功 + if (reConsume == 3) { + // TODO 补偿信息 + //smsLogService.insertLog(topic, tags, msgId, keys, body, "【" + EnumUtil.getStrMsgByCode(tags, TagsCodeEnum.class) + "】消费失败"); + log.error("消息重试超过3次,消费失败!"); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + // 订单超时处理 + if (MessageCodeEnum.ORDER_MESSAGE.getCode().equals(topic)) { + if (MessageCodeEnum.ORDER_TIMEOUT_TAG.getCode().equals(tags)) { +// //获取订单 +// DealUserOrder dealUserOrder = pcRemoteDealUserOrderService.selectDealUserOrderByOrderNumber(keys); +// if (dealUserOrder != null) { +// //订单状态超时未支付关闭订单 处理 +// if (dealUserOrder.getStatus().equals("1")) { +// DealUserOrder dealUserOrders = new DealUserOrder(); +// dealUserOrders.setOrderId(dealUserOrder.getOrderId()); +// dealUserOrders.setStatus("4"); +// pcRemoteDealUserOrderService.updateDealUserOrder(dealUserOrders); +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; +// } +// log.info("Order does not exist."); +// } + log.info("Consumption success:" + body); + DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + log.info("Consumption time:{}", format.format(new Date())); + } else { + log.info("未匹配到Tag【{}】" + tags); + } + } + } + } + // 消息消费成功 + //ConsumeConcurrentlyStatus.RECONSUME_LATER broker会根据设置的messageDelayLevel发起重试,默认16次 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + /** + * 异常处理 + * + * @param e 捕获的异常 + * @return 消息消费结果 + */ + private static ConsumeConcurrentlyStatus handleException(final Exception e) { + Class exceptionClass = e.getClass(); + if (exceptionClass.equals(UnsupportedEncodingException.class)) { + log.error(e.getMessage()); + } else if (exceptionClass.equals(ConsumeException.class)) { + log.error(e.getMessage()); + } + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/enums/MessageCodeEnum.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/enums/MessageCodeEnum.java new file mode 100644 index 00000000..b720834c --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/enums/MessageCodeEnum.java @@ -0,0 +1,60 @@ +package com.yanzhu.testrocketmq.enums; + + +import lombok.Getter; + +@Getter +public enum MessageCodeEnum { + /** + * 消息模块主题 + */ + MESSAGE_TOPIC("elink-message","消息服务模块topic名称"), + /** + * 系统消息 + */ + NOTE_MESSAGE("system-message","系统消息服务模块topic名称"), + /** + * 用户消息 + */ + USER_MESSAGE("user-message","用户消息服务模块topic名称"), + + /** + * 订单消息 + */ + ORDER_MESSAGE("order-message","订单消息服务模块topic名称"), + + /** + * 平台编号 + */ + USER_MESSAGE_TAG("user_message_tag","用户消息推送"), + NOTE_MESSAGE_TAG("system_message_tag","系统消息推送"), + ORDER_MESSAGE_TAG("order_message_tag","订单消息推送"), + + /** + * 订单处理编号 + */ + //订单超时处理 + ORDER_TIMEOUT_TAG("order_timeout_tag","订单超时处理"); + + + private final String code; + private final String msg; + + MessageCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + + public static String valuesOfType(String code) { + String value = ""; + for (MessageCodeEnum e : MessageCodeEnum.values()) { + if (code.equals(e.code)) { + value = e.msg; + } + + } + return value; + } + + +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ConsumerMode.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ConsumerMode.java new file mode 100644 index 00000000..901c37cb --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ConsumerMode.java @@ -0,0 +1,22 @@ +package com.yanzhu.testrocketmq.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +@Data +@Configuration +@Component +public class ConsumerMode { + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.conumer.groupName}") + private String groupName ; + @Value("${suning.rocketmq.conumer.consumeThreadMin}") + private int consumeThreadMin; + @Value("${suning.rocketmq.conumer.consumeThreadMax}") + private int consumeThreadMax; + @Value("${suning.rocketmq.conumer.consumeMessageBatchMaxSize}") + private int consumeMessageBatchMaxSize; +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ProducerMode.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ProducerMode.java new file mode 100644 index 00000000..85915d6d --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/model/ProducerMode.java @@ -0,0 +1,25 @@ +package com.yanzhu.testrocketmq.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 生产者初始化 + */ +@RefreshScope +@Data +@Configuration +public class ProducerMode { + @Value("${suning.rocketmq.producer.groupName}") + private String groupName; + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.producer.maxMessageSize}") + private Integer maxMessageSize; + @Value("${suning.rocketmq.producer.sendMsgTimeout}") + private Integer sendMsgTimeout; + @Value("${suning.rocketmq.producer.retryTimesWhenSendFailed}") + private Integer retryTimesWhenSendFailed; +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/AsyncProducer.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/AsyncProducer.java new file mode 100644 index 00000000..d744d8b7 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/AsyncProducer.java @@ -0,0 +1,47 @@ +package com.yanzhu.testrocketmq.producer; + +import com.yanzhu.testrocketmq.config.ProducerConfig; +import org.springframework.beans.factory.annotation.Autowired; + +public class AsyncProducer { + + @Autowired + private ProducerConfig producerConfig; + + /** + * 发送异步的消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * @return org.apache.rocketmq.client.producer.SendResult + */ +// public SendResult sendAsyncProducerMessage(String topic, String tag, String key, String value) throws UnsupportedEncodingException { +// +// try { +// DefaultMQProducer defaultMQProducer = producerConfig.producer; +// //Create a message instance, specifying topic, tag and message body. +// Message msg = new Message(topic, tag, key,value.getBytes(RemotingHelper.DEFAULT_CHARSET)); +// defaultMQProducer.send(msg, new SendCallback() { +// // 异步回调的处理 +// @Override +// public void onSuccess(SendResult sendResult) { +// System.out.printf("%-10d 异步发送消息成功 %s %n", msg, sendResult.getMsgId()); +// } +// +// @Override +// public void onException(Throwable e) { +// System.out.printf("%-10d 异步发送消息失败 %s %n", msg, e); +// e.printStackTrace(); +// } +// }); +// } catch (MQClientException e) { +// e.printStackTrace(); +// } catch (RemotingException e) { +// e.printStackTrace(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// return null; +// } +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/ConsumeException.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/ConsumeException.java new file mode 100644 index 00000000..5fa63a19 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/ConsumeException.java @@ -0,0 +1,20 @@ +package com.yanzhu.testrocketmq.producer; + +/** + * @author 影子 + */ +public class ConsumeException extends RuntimeException{ + private static final long serialVersionUID = 4093867789628938836L; + + public ConsumeException(String message) { + super(message); + } + + public ConsumeException(Throwable cause) { + super(cause); + } + + public ConsumeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageContext.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageContext.java new file mode 100644 index 00000000..8c4bbec4 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageContext.java @@ -0,0 +1,34 @@ +package com.yanzhu.testrocketmq.producer; + + + +import lombok.Data; +import lombok.ToString; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageQueue; + +/** + * 消费时,当前所消费的消息的上下文信息 + * + * @author jolly + */ +@ToString +@Data +public final class MessageContext { + + /** + * 所消费消息所在的消息队列 + * + * @see MessageQueue + */ + private MessageQueue messageQueue; + + /** + * 所消费的消息的扩展属性 + * + * @see MessageExt + */ + private MessageExt messageExt; + + +} diff --git a/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageProducer.java b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageProducer.java new file mode 100644 index 00000000..81404d38 --- /dev/null +++ b/yanzhu-rocketmq/src/test/java/com/yanzhu/testrocketmq/producer/MessageProducer.java @@ -0,0 +1,110 @@ +package com.yanzhu.testrocketmq.producer; + +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import static com.yanzhu.rocketmq.config.ProducerConfig.producer; + +/** + * 消息发送 + */ +@Slf4j +public class MessageProducer { + + + /** + * 同步发送消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * @return org.apache.rocketmq.client.producer.SendResult + */ + public SendResult sendSynchronizeMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + SendResult result = producer.send(msg); + return result; + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException | InterruptedException | RemotingException | MQBrokerException e) { + log.error("消息发送失败! body:{}",body); + } + return null; + } + + + + /** + * 发送有序的消息 + * @param messagesList Message集合 + * @param messageQueueNumber 消息队列编号 + * @return org.apache.rocketmq.client.producer.SendResult + */ + public SendResult sendOrderlyMessage(List messagesList, int messageQueueNumber) { + SendResult result = null; + for (Message message : messagesList) { + try { +// DefaultMQProducer defaultMQProducer = ProducerConfig.producer.send(message); +// System.out.println(defaultMQProducer); + result = producer.send(message, (list, msg, arg) -> { + Integer queueNumber = (Integer) arg; + return list.get(queueNumber); + }, messageQueueNumber); + } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) { + log.error("发送有序消息失败"); + return result; + } + } + return result; + } + + /** + * 推送延迟消息 + * @param topic + * @param tag + * @param key + * @return boolean + */ + public SendResult sendDelayMessage(String topic, String tag, String key, String value) + { + SendResult result = null; + try + { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + //设置消息延迟级别,我这里设置5,对应就是延时一分钟 + // "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" + msg.setDelayTimeLevel(4); + // 发送消息到一个Broker + result = producer.send(msg); + // 通过sendResult返回消息是否成功送达 + log.info("发送延迟消息结果:======sendResult:{}", result); + DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + log.info("发送时间:{}", format.format(new Date())); + return result; + } + catch (Exception e) + { + e.printStackTrace(); + log.error("延迟消息队列推送消息异常:{},推送内容:{}", e.getMessage(), result); + } + return result; + } + + +} diff --git a/yanzhu-ui-app/App.vue b/yanzhu-ui-app/App.vue new file mode 100644 index 00000000..95bb2f22 --- /dev/null +++ b/yanzhu-ui-app/App.vue @@ -0,0 +1,28 @@ + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/LICENSE b/yanzhu-ui-app/LICENSE new file mode 100644 index 00000000..2c46dbaf --- /dev/null +++ b/yanzhu-ui-app/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 若依 + +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. diff --git a/yanzhu-ui-app/README.md b/yanzhu-ui-app/README.md new file mode 100644 index 00000000..95b2ab4f --- /dev/null +++ b/yanzhu-ui-app/README.md @@ -0,0 +1,52 @@ +

+ logo +

+

RuoYi v1.1.0

+

基于UniApp开发的轻量级移动端框架

+

+ + + +

+ +## 平台简介 + +RuoYi App 移动解决方案,采用uniapp框架,一份代码多终端适配,同时支持APP、小程序、H5!实现了与[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)、[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)完美对接的移动解决方案!目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。 + +* 配套后端代码仓库地址[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) 或 [RuoYi-Cloud](https://github.com/yangzongzhuan/RuoYi-Cloud) 版本。 +* 应用框架基于[uniapp](https://uniapp.dcloud.net.cn/),支持小程序、H5、Android和IOS。 +* 前端组件采用[uni-ui](https://github.com/dcloudio/uni-ui),全端兼容的高性能UI框架。 +* 阿里云折扣场:[点我进入](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)   + + +## 技术文档 + +- 官网网站:[http://ruoyi.vip](http://ruoyi.vip) +- 文档地址:[http://doc.ruoyi.vip](http://doc.ruoyi.vip) +- H5页体验:[http://h5.ruoyi.vip](http://h5.ruoyi.vip) +- QQ交流群: ①133713780(满)、②146013835 +- 小程序体验 + +小程序演示 + + +## 演示图 + + + + + + + + + + + + + + + + + +
diff --git a/yanzhu-ui-app/api/callup.js b/yanzhu-ui-app/api/callup.js new file mode 100644 index 00000000..7f18bf68 --- /dev/null +++ b/yanzhu-ui-app/api/callup.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' +import upload from '@/utils/upload' + +// 上传文件 +export function saveFileManagement(data) { + return request({ + url: '/apiwork/fileApi/saveFileManagement', + method: 'post', + data:data + }) +} + +// 下载文件时调用 +export function countLikeNum(val) { + return request({ + url: '/apiwork/fileApi/countLikeNum/' + val, + method: 'get', + }) +} + +// 点赞/取消点赞 +export function fileApilike(val) { + return request({ + url: '/apiwork/fileApi/like/' + val, + method: 'get', + }) +} + +// 宣传资料列表 +export function findAll(data) { + return request({ + url: '/apiwork/fileApi/findAll', + method: 'get', + data: data, + }) +} + +// 工單提交 +export function submitWork(data) { + return request({ + 'url': '/apiwork/work/tzzrz/createTzzWork', + method: 'post', + data: data, + }) +} +// 文件上传 +export function uploadFile(data) { + return upload({ + url: '/common/upload', + method:'PUT', + name: data.name, + filePath: data.filePath + }) +} + +// 查询意见反馈类型列表 +export function ideaType(data) { + return request({ + 'url': '/apiwork/tyPublicApi/idea/v1/ideaType', + method: 'get' + }) +} + +// 提交反馈 +export function feedbackSub(data) { + return request({ + 'url': '/apiwork/tyPublicApi/idea/v1/add', + method: 'post', + data: data, + }) +} \ No newline at end of file diff --git a/yanzhu-ui-app/api/index.js b/yanzhu-ui-app/api/index.js new file mode 100644 index 00000000..3c36f0de --- /dev/null +++ b/yanzhu-ui-app/api/index.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' + +// 预警消息 +export function update(data) { + return request({ + url: '/system/warning', + method: 'put', + data:data + }) +} + +// 预警消息 +export function warningList(query) { + return request({ + url: '/system/warning/list', + method: 'get', + params: query + }) +} + +// 新增投诉工单 +export function addOrder(data) { + return request({ + url: '/system/order', + method: 'post', + data: data + }) +} + +// 查询投诉列表 +export function listuser(query) { + return request({ + url: '/system/order/listuser', + method: 'get', + params: query + }) +} + +// 查询工单列表 +export function listOrder(query) { + return request({ + url: '/system/order/list', + method: 'get', + params: query + }) +} + +// 查询工单列表 +export function recordOrder(id) { + return request({ + url: '/system/record/list?workOrderId=' + id, + method: 'get' + }) +} + +// 签到/完成任务 +export function record(query) { + return request({ + url: '/system/order/task/record', + method: 'post', + data: query + }) +} + +// 查询工单详情 +export function getOrder(id) { + return request({ + url: '/system/order/' + id, + method: 'get' + }) +} \ No newline at end of file diff --git a/yanzhu-ui-app/api/login.js b/yanzhu-ui-app/api/login.js new file mode 100644 index 00000000..4705475f --- /dev/null +++ b/yanzhu-ui-app/api/login.js @@ -0,0 +1,50 @@ +import request from '@/utils/request' + +// 获取用户详细信息 +export function getInfo() { + return request({ + 'url': '/wechat/userinfo/getUserInfo', + 'method': 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + 'url': '/auth/logout', + 'method': 'delete' + }) +} + +//手机号登陆 +export function phoneLogin(data) { + return request({ + url: '/auth/phoneLogin', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +//获取OPENID 存sessionkey +export function getOpenIdByCode(data) { + return request({ + url: '/auth/getOpenIdByCode', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +//获取微信手机号 +export function getWxUserPhone(data) { + return request({ + url: '/auth/getWxUserPhone', + method: 'post', + data: data + }) +} diff --git a/yanzhu-ui-app/components/navbar/Navbar.vue b/yanzhu-ui-app/components/navbar/Navbar.vue new file mode 100644 index 00000000..28bc775b --- /dev/null +++ b/yanzhu-ui-app/components/navbar/Navbar.vue @@ -0,0 +1,83 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/components/navbar/homebar.vue b/yanzhu-ui-app/components/navbar/homebar.vue new file mode 100644 index 00000000..7ab3c4d5 --- /dev/null +++ b/yanzhu-ui-app/components/navbar/homebar.vue @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/components/tabbar.vue b/yanzhu-ui-app/components/tabbar.vue new file mode 100644 index 00000000..e417830d --- /dev/null +++ b/yanzhu-ui-app/components/tabbar.vue @@ -0,0 +1,99 @@ + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/components/uni-section/uni-section.vue b/yanzhu-ui-app/components/uni-section/uni-section.vue new file mode 100644 index 00000000..9a52e0b8 --- /dev/null +++ b/yanzhu-ui-app/components/uni-section/uni-section.vue @@ -0,0 +1,167 @@ + + + + diff --git a/yanzhu-ui-app/config.js b/yanzhu-ui-app/config.js new file mode 100644 index 00000000..fffa5bc4 --- /dev/null +++ b/yanzhu-ui-app/config.js @@ -0,0 +1,27 @@ +// 应用全局配置 +module.exports = { + // test + baseUrl: 'http://192.168.16.104:8080', + // baseUrl: 'http://192.168.16.104:8080', + // 应用信息 + appInfo: { + // 应用名称 + name: "ruoyi-app", + // 应用版本 + version: "1.1.0", + // 应用logo + logo: "/static/logo.png", + // 官方网站 + site_url: "http://ruoyi.vip", + // 政策协议 + agreements: [{ + title: "隐私政策", + url: "" + }, + { + title: "用户服务协议", + url: "" + } + ] + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/main.js b/yanzhu-ui-app/main.js new file mode 100644 index 00000000..a682b47a --- /dev/null +++ b/yanzhu-ui-app/main.js @@ -0,0 +1,26 @@ +import Vue from 'vue' +import App from './App' +import store from './store' // store +import plugins from './plugins' // plugins +import uView from '@/uview-ui' //uview +import './permission' // permission +import homebar from "@/components/navbar/homebar.vue" +import navbar from "@/components/navbar/Navbar.vue" +// import Vconsole from 'vconsole' +// let vConsole = new Vconsole(); + +Vue.use(plugins) +Vue.use(uView) +Vue.config.productionTip = false +Vue.prototype.$store = store +Vue.component('homebar', homebar) +Vue.component('navbar', navbar) +App.mpType = 'app' + +const app = new Vue({ + ...App +}) + +app.$mount() + +// export default vConsole \ No newline at end of file diff --git a/yanzhu-ui-app/manifest.json b/yanzhu-ui-app/manifest.json new file mode 100644 index 00000000..a3f137b7 --- /dev/null +++ b/yanzhu-ui-app/manifest.json @@ -0,0 +1,85 @@ +{ + "name" : "移动端", + "appid" : "__UNI__A076EAE", + "description" : "", + "versionName" : "1.1.0", + "versionCode" : "100", + "transformPx" : false, + "app-plus" : { + "usingComponents" : true, + "nvueCompiler" : "急用工", + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + "modules" : {}, + "distribute" : { + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + "ios" : {}, + "sdkConfigs" : { + "maps" : { + "amap" : { + "appkey_ios" : "", + "appkey_android" : "" + } + } + } + } + }, + "quickapp" : {}, + "mp-weixin" : { + "appid" : "wxbde64edd3cb15f72", + "setting" : { + "urlCheck" : false, + "es6" : true, + "minified" : true, + "postcss" : true + }, + "optimization" : { + "subPackages" : true + }, + "usingComponents" : true, + "permission" : { + "scope.userLocation" : { + "desc" : "你的位置信息将用于小程序位置接口的效果展示" + } + }, + "requiredPrivateInfos" : [ "chooseAddress", "chooseLocation", "getLocation" ], + "unipush" : { + "enable" : false + } + }, + "vueVersion" : "2", + "h5" : { + "template" : "static/index.html", + "devServer" : { + "port" : 9090, + "https" : false + }, + "title" : "水务投诉平台", + "router" : { + "mode" : "hash", + "base" : "./" + }, + "sdkConfigs" : { + "maps" : { + "qqmap" : { + "key" : "IO6BZ-EJALJ-PXDF5-XOVE6-VRWPO-DUFTO" + } + } + } + } +} diff --git a/yanzhu-ui-app/package-lock.json b/yanzhu-ui-app/package-lock.json new file mode 100644 index 00000000..5ffa6382 --- /dev/null +++ b/yanzhu-ui-app/package-lock.json @@ -0,0 +1,24 @@ +{ + "name": "v-wordbench", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "weixin-js-sdk": "^1.6.5" + } + }, + "node_modules/weixin-js-sdk": { + "version": "1.6.5", + "resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz", + "integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ==" + } + }, + "dependencies": { + "weixin-js-sdk": { + "version": "1.6.5", + "resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz", + "integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ==" + } + } +} diff --git a/yanzhu-ui-app/package.json b/yanzhu-ui-app/package.json new file mode 100644 index 00000000..2b02866d --- /dev/null +++ b/yanzhu-ui-app/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "weixin-js-sdk": "^1.6.5" + } +} diff --git a/yanzhu-ui-app/pages.json b/yanzhu-ui-app/pages.json new file mode 100644 index 00000000..c8eec602 --- /dev/null +++ b/yanzhu-ui-app/pages.json @@ -0,0 +1,202 @@ +{ + "easycom": { + "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" + }, + "pages": [{ + "path": "pages/login", + "style": { + "navigationBarTitleText": "登录", + "navigationStyle": "custom" + } + }, { + "path": "pages/centerlogin", + "style": { + "navigationBarTitleText": "登录身份", + "navigationStyle": "custom" + } + }, { + "path": "pages/information/index", + "style": { + "navigationBarTitleText": "完善信息", + "navigationStyle": "custom" + } + }, { + "path": "pages/index", + "style": { + "navigationBarTitleText": " 任务", + "navigationStyle": "custom" + } + }, + { + "path": "pages/work/index", + "style": { + "navigationBarTitleText": "消息", + "navigationStyle": "custom" + } + }, + { + "path": "pages/mine/index", + "style": { + "navigationBarTitleText": "我的", + "navigationStyle": "custom" + } + }, + { + "path": "pages/information/index2", + "style": { + "navigationBarTitleText": "完善学历", + "navigationStyle": "custom" + } + }, + { + "path": "pages/information/index3", + "style": { + "navigationBarTitleText": "兼职意向", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/information/index4", + "style": { + "navigationBarTitleText": "完善简历", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/information/end", + "style": { + "navigationBarTitleText": "兼职人员注册成功", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/workNext/index", + "style": { + "navigationBarTitleText": "完善公司个人信息", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/workNext/index2", + "style": { + "navigationBarTitleText": "完善公司信息", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/workNext/index3", + "style": { + "navigationBarTitleText": "发布兼职", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/listdeil/index", + "style": { + "navigationBarTitleText": "职位详情", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path" : "pages/work/deilorder", + "style" : + { + "navigationBarTitleText" : "信息职位详情", + "enablePullDownRefresh" : false, + "navigationStyle": "custom" + } + } + ], + "subPackages": [{ + "root": "pages_loader", + "pages": [{ + "path": "pages/index", + "style": { + "navigationBarTitleText": "人才大厅", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/work/index", + "style": { + "navigationBarTitleText": "消息", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/mine/index", + "style": { + "navigationBarTitleText": "我的", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/listdeil/index", + "style": { + "navigationBarTitleText": "人才详情", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/release", + "style": { + "navigationBarTitleText": "发布兼职", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path" : "pages/work/deilorder", + "style" : + { + "navigationBarTitleText" : "沟通人才详情", + "enablePullDownRefresh" : false, + "navigationStyle": "custom" + } + } + ] + }], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#FFFFFF", + "backgroundColor": "#FFFFFF" + } + // "tabBar": { + // "color": "#000000", + // "selectedColor": "#000000", + // "borderStyle": "white", + // "backgroundColor": "#fff", + // "borderStyle": "black", + // "list": [{ + // "pagePath": "pages/index", + // "iconPath": "static/tabarimg/fz1.png", + // "selectedIconPath": "static/tabarimg/fz2.png", + // "text": "首页" + // }, + // { + // "pagePath": "pages/work/index", + // "iconPath": "static/tabarimg/fz3.png", + // "selectedIconPath": "static/tabarimg/fz4.png", + // "text": "消息" + // }, + // { + // "pagePath": "pages/mine/index", + // "iconPath": "static/tabarimg/fz3.png", + // "selectedIconPath": "static/tabarimg/fz4.png", + // "text": "我的" + // } + // ] + // } +} \ No newline at end of file diff --git a/yanzhu-ui-app/pages/centerlogin.vue b/yanzhu-ui-app/pages/centerlogin.vue new file mode 100644 index 00000000..d41e0ec7 --- /dev/null +++ b/yanzhu-ui-app/pages/centerlogin.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/yanzhu-ui-app/pages/index.vue b/yanzhu-ui-app/pages/index.vue new file mode 100644 index 00000000..f69207be --- /dev/null +++ b/yanzhu-ui-app/pages/index.vue @@ -0,0 +1,191 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/information/end.vue b/yanzhu-ui-app/pages/information/end.vue new file mode 100644 index 00000000..31ed77d6 --- /dev/null +++ b/yanzhu-ui-app/pages/information/end.vue @@ -0,0 +1,103 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/information/index.vue b/yanzhu-ui-app/pages/information/index.vue new file mode 100644 index 00000000..2229a7b8 --- /dev/null +++ b/yanzhu-ui-app/pages/information/index.vue @@ -0,0 +1,109 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/information/index2.vue b/yanzhu-ui-app/pages/information/index2.vue new file mode 100644 index 00000000..dadc4546 --- /dev/null +++ b/yanzhu-ui-app/pages/information/index2.vue @@ -0,0 +1,94 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/information/index3.vue b/yanzhu-ui-app/pages/information/index3.vue new file mode 100644 index 00000000..13e28750 --- /dev/null +++ b/yanzhu-ui-app/pages/information/index3.vue @@ -0,0 +1,103 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/information/index4.vue b/yanzhu-ui-app/pages/information/index4.vue new file mode 100644 index 00000000..07d837b2 --- /dev/null +++ b/yanzhu-ui-app/pages/information/index4.vue @@ -0,0 +1,101 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/listdeil/index.vue b/yanzhu-ui-app/pages/listdeil/index.vue new file mode 100644 index 00000000..7dba5929 --- /dev/null +++ b/yanzhu-ui-app/pages/listdeil/index.vue @@ -0,0 +1,164 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/login.vue b/yanzhu-ui-app/pages/login.vue new file mode 100644 index 00000000..dd7e8e27 --- /dev/null +++ b/yanzhu-ui-app/pages/login.vue @@ -0,0 +1,372 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/mine/index.vue b/yanzhu-ui-app/pages/mine/index.vue new file mode 100644 index 00000000..e9fbfc7a --- /dev/null +++ b/yanzhu-ui-app/pages/mine/index.vue @@ -0,0 +1,70 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/work/deilorder.vue b/yanzhu-ui-app/pages/work/deilorder.vue new file mode 100644 index 00000000..ef43a0b6 --- /dev/null +++ b/yanzhu-ui-app/pages/work/deilorder.vue @@ -0,0 +1,178 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/work/index.vue b/yanzhu-ui-app/pages/work/index.vue new file mode 100644 index 00000000..81b7793a --- /dev/null +++ b/yanzhu-ui-app/pages/work/index.vue @@ -0,0 +1,134 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/workNext/index.vue b/yanzhu-ui-app/pages/workNext/index.vue new file mode 100644 index 00000000..0a40116c --- /dev/null +++ b/yanzhu-ui-app/pages/workNext/index.vue @@ -0,0 +1,176 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/workNext/index2.vue b/yanzhu-ui-app/pages/workNext/index2.vue new file mode 100644 index 00000000..8b480ad6 --- /dev/null +++ b/yanzhu-ui-app/pages/workNext/index2.vue @@ -0,0 +1,177 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages/workNext/index3.vue b/yanzhu-ui-app/pages/workNext/index3.vue new file mode 100644 index 00000000..274e958d --- /dev/null +++ b/yanzhu-ui-app/pages/workNext/index3.vue @@ -0,0 +1,190 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages_loader/pages/index.vue b/yanzhu-ui-app/pages_loader/pages/index.vue new file mode 100644 index 00000000..7bdcfb82 --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/index.vue @@ -0,0 +1,161 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages_loader/pages/listdeil/index.vue b/yanzhu-ui-app/pages_loader/pages/listdeil/index.vue new file mode 100644 index 00000000..7ee9f91a --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/listdeil/index.vue @@ -0,0 +1,80 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages_loader/pages/mine/index.vue b/yanzhu-ui-app/pages_loader/pages/mine/index.vue new file mode 100644 index 00000000..94962295 --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/mine/index.vue @@ -0,0 +1,55 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages_loader/pages/release.vue b/yanzhu-ui-app/pages_loader/pages/release.vue new file mode 100644 index 00000000..b4b7acd2 --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/release.vue @@ -0,0 +1,190 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/pages_loader/pages/work/deilorder.vue b/yanzhu-ui-app/pages_loader/pages/work/deilorder.vue new file mode 100644 index 00000000..1398f4f5 --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/work/deilorder.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/yanzhu-ui-app/pages_loader/pages/work/index.vue b/yanzhu-ui-app/pages_loader/pages/work/index.vue new file mode 100644 index 00000000..f48fc9e4 --- /dev/null +++ b/yanzhu-ui-app/pages_loader/pages/work/index.vue @@ -0,0 +1,123 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/permission.js b/yanzhu-ui-app/permission.js new file mode 100644 index 00000000..28bfcf9d --- /dev/null +++ b/yanzhu-ui-app/permission.js @@ -0,0 +1,45 @@ +import { + getToken +} from '@/utils/auth' + +// 登录页面 +const loginPage = "/pages/login" +// 登录失效页面 +const loginFail = "/pages/login" +// 页面白名单 +const whiteList = [ ] + +// 检查地址白名单 +// function checkWhite(url) { +// const path = url.split('?')[0] +// //console.log(path+"全连接") +// return whiteList.indexOf(path) !== -1 +// } + +// 页面跳转验证拦截器 +// let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"] +// list.forEach(item => { +// uni.addInterceptor(item, { +// invoke(to) { +// if (getToken()) { +// if (to.url === loginFail) { +// uni.reLaunch({ +// url: "/" +// }) +// } +// return true +// } else { +// if (checkWhite(to.url)) { +// return true +// } +// uni.reLaunch({ +// url: "/" +// }) +// return false +// } +// }, +// fail(err) { +// //console.log(err) +// } +// }) +// }) \ No newline at end of file diff --git a/yanzhu-ui-app/plugins/auth.js b/yanzhu-ui-app/plugins/auth.js new file mode 100644 index 00000000..3b91c14e --- /dev/null +++ b/yanzhu-ui-app/plugins/auth.js @@ -0,0 +1,60 @@ +import store from '@/store' + +function authPermission(permission) { + const all_permission = "*:*:*" + const permissions = store.getters && store.getters.permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "admin" + const roles = store.getters && store.getters.roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 验证用户是否具备某权限 + hasPermi(permission) { + return authPermission(permission) + }, + // 验证用户是否含有指定权限,只需包含其中一个 + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 验证用户是否含有指定权限,必须全部拥有 + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 验证用户是否具备某角色 + hasRole(role) { + return authRole(role) + }, + // 验证用户是否含有指定角色,只需包含其中一个 + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 验证用户是否含有指定角色,必须全部拥有 + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} diff --git a/yanzhu-ui-app/plugins/index.js b/yanzhu-ui-app/plugins/index.js new file mode 100644 index 00000000..efbae151 --- /dev/null +++ b/yanzhu-ui-app/plugins/index.js @@ -0,0 +1,14 @@ +import tab from './tab' +import auth from './auth' +import modal from './modal' + +export default { + install(Vue) { + // 页签操作 + Vue.prototype.$tab = tab + // 认证对象 + Vue.prototype.$auth = auth + // 模态框对象 + Vue.prototype.$modal = modal + } +} diff --git a/yanzhu-ui-app/plugins/modal.js b/yanzhu-ui-app/plugins/modal.js new file mode 100644 index 00000000..99b2215f --- /dev/null +++ b/yanzhu-ui-app/plugins/modal.js @@ -0,0 +1,74 @@ +export default { + // 消息提示 + msg(content) { + uni.showToast({ + title: content, + icon: 'none' + }) + }, + // 错误消息 + msgError(content) { + uni.showToast({ + title: content, + icon: 'error' + }) + }, + // 成功消息 + msgSuccess(content) { + uni.showToast({ + title: content, + icon: 'success' + }) + }, + // 隐藏消息 + hideMsg(content) { + uni.hideToast() + }, + // 弹出提示 + alert(content, title) { + uni.showModal({ + title: title || '系统提示', + content: content, + showCancel: false + }) + }, + // 确认窗体 + confirm(content, title) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: title || '系统提示', + content: content, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + if (res.confirm) { + resolve(res.confirm) + } + } + }) + }) + }, + // 提示信息 + showToast(option) { + if (typeof option === "object") { + uni.showToast(option) + } else { + uni.showToast({ + title: option, + icon: "none", + duration: 2500 + }) + } + }, + // 打开遮罩层 + loading(content) { + uni.showLoading({ + title: content, + icon: 'none' + }) + }, + // 关闭遮罩层 + closeLoading() { + uni.hideLoading() + } +} diff --git a/yanzhu-ui-app/plugins/tab.js b/yanzhu-ui-app/plugins/tab.js new file mode 100644 index 00000000..5d1b3058 --- /dev/null +++ b/yanzhu-ui-app/plugins/tab.js @@ -0,0 +1,30 @@ +export default { + // 关闭所有页面,打开到应用内的某个页面 + reLaunch(url) { + return uni.reLaunch({ + url: url + }) + }, + // 跳转到tabBar页面,并关闭其他所有非tabBar页面 + switchTab(url) { + return uni.switchTab({ + url: url + }) + }, + // 关闭当前页面,跳转到应用内的某个页面 + redirectTo(url) { + return uni.redirectTo({ + url: url + }) + }, + // 保留当前页面,跳转到应用内的某个页面 + navigateTo(url) { + return uni.navigateTo({ + url: url + }) + }, + // 关闭当前页面,返回上一页面或多级页面 + navigateBack() { + return uni.navigateBack() + } +} diff --git a/yanzhu-ui-app/project.config.json b/yanzhu-ui-app/project.config.json new file mode 100644 index 00000000..958f468d --- /dev/null +++ b/yanzhu-ui-app/project.config.json @@ -0,0 +1,31 @@ +{ + "compileType": "miniprogram", + "setting": { + "coverView": true, + "es6": true, + "postcss": true, + "minified": true, + "enhance": true, + "showShadowRootInWxmlPanel": true, + "packNpmRelationList": [], + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "ignoreUploadUnusedFiles": true, + "condition": false + }, + + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 4 + }, + "libVersion": "3.2.0", + "packOptions": { + "ignore": [], + "include": [] + }, + "appid": "" +} \ No newline at end of file diff --git a/yanzhu-ui-app/project.private.config.json b/yanzhu-ui-app/project.private.config.json new file mode 100644 index 00000000..a120190b --- /dev/null +++ b/yanzhu-ui-app/project.private.config.json @@ -0,0 +1,7 @@ +{ + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "projectname": "applet-fucai", + "setting": { + "compileHotReLoad": true + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/static/doc.png b/yanzhu-ui-app/static/doc.png new file mode 100644 index 0000000000000000000000000000000000000000..9131f92849bf47cafb2b9e15e8b2454260bb88e4 GIT binary patch literal 1905 zcmb_ddozW1DazV~KfJzNwO;0gc$ zD571RaFDOxzw)w>jdiPOgPcSR&IJWDztCKQh;$4J?IjPLB>5}10YFXz?d0GUU-n_n zJW7M0HoW!*Y1vf&nK722;~5NG%F3S2C?QLn5J_IRbEn>>#@*Y6m;odMc3!)K0udS@9y#UX6ItYg<^N_%ih4WV{(1l2?WMcgeOr!m+^=fgMF%e5V^CmS`a8X`)2}w%;>Dz~SXwC9u^QFc z`smS7kLSzAfsdtuT0Mr&+KDFd%!idyKbag`mx=0SKPKWJ8cmgPunP#9CAi<7;;ZLo#xncvh6rD}8t zki^gr0ZD$s5ooZ&DsL!!{r=e&{**VA(pVX^d+MJT>`a5TJ^7>@saZMvEVmG}ni8sR zc(BM8P!)~!>wLvC>5kA#Y$;#eAtomRe6`8!nk zAzQKI*(Ig1xdIEUqv(6h$Jey~;J#5>6R*0hXu~x2!gujFeMjO70`?$|8kR5Fr8qCF zQeKok`J0*neaIe-l)cbkj>VC{{76`#R~VHBm-=5)%y*A(bat8LjdN0yw|VW%^OII$ z3PLzKQJw1Eu@XiMF=btL^Nq$YJu7+a>r-Da91u{fz1N-dmSmdw^5&Pr_v0Ok71kTA z_4l?%CmgR4*D+c_a4Bd(Rq1QE4D53q_OE(MWO@XvQ}1BPY(}FYkg4{;VvWM z^r(KjTRxbP@E`=0D>o9TqRT}PJuqJzVMozNtCk~<5+(dYjaaNix2&vVN7C7Br2}4q zU4JQ0FtfqvScES395MU3f+v`=H}U34>gUK;Q}&*99qp=imF_ZdJ!J7zzvt_u_cBj9 zOH^i-mD2f7aG~_D(u}f}cJal2KdLSb&IrNU<}KDnia^c0LdKf6buOhn3@!vEZ{kyM@8Q1$bQ($|Y)1}Tno5$) z)m>itPE@K6zGE*EQz_Z@o|8#0FFw4xMYcQ5Lqs1oz+Pk4?Hc#G(sYN{A95sIz#%o6 z0#SIvN-39U$HY*bCzD1*l-no6nTh`Vv}${>3we5N;m%Y`MKq&g(TJsnvpcA)xIB~h z=I|H4Ae$vAyQn}{Sw5D@raXWh6SGUdbqof)=wNPnTD;)OP#wF zMEfRbBq1R=E|QibOogpa`NX9uYn@FzncK8FKYIsf(!vkD-fEY!+q4Sce@>PqqKX9b z8uu6h%T6QB!*R{WR&$R0pa1zk284+T%a}J(CR;+8lGit&7>x@(p1pwsiN+O@DoDr6|F5eN+)au<&tlXbz7c*A>L)7x+VKCTFw8^v`| xKnfAj^vMU%dH&Fff01OvDXu1%B9RwG%D_3-&@ZGf6+>$iKs$RlHKRh({|0aQi`f7G literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/favicon.ico b/yanzhu-ui-app/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..83e523bd96488b226fa336673c55a7e5fdaf6994 GIT binary patch literal 16958 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/fileimg.png b/yanzhu-ui-app/static/fileimg.png new file mode 100644 index 0000000000000000000000000000000000000000..455281fdb3c8a1827f0241a11d09ccdd63eca65a GIT binary patch literal 6213 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/ation.png b/yanzhu-ui-app/static/images/ation.png new file mode 100644 index 0000000000000000000000000000000000000000..4e9a4a0bda9ebd882e94efa481a8acdc13f17d43 GIT binary patch literal 12396 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


R2GJpMzIfW#S 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 OKM2!H=PHb^-1tB47luv% literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/clzgb.png b/yanzhu-ui-app/static/images/clzgb.png new file mode 100644 index 0000000000000000000000000000000000000000..fab1d1171ebda0d606c845518f28065d5ef99ffa GIT binary patch literal 6483 zcmV-Z8LZ}sP)Px#1am@3R0s$N2z&@+hyVZ>{YgYYRCt{2T}w_QO%n`{5vM>xVqq?Wk>(V009N<_ zX2k)%Qy^h3Grd4U;uL6F{ugxipDx!U>s@6W(nt)rAFhthipfeYJBdnCHsW1@P z&qR0QOlStOyyMqmJ^iXQd8L?1zPsMM)xMdQ@Z$;n`*XYMfWS`dm-`)XCisseG$V1h z1h(NPll#XI`qW8m!cQajNfTOe=yDVJz**x_3lmB^n)~H`ck0AGNkV6|#slz8){Eu$ z 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/doudi.png b/yanzhu-ui-app/static/images/doudi.png new file mode 100644 index 0000000000000000000000000000000000000000..eb7a694828011cb2eae58baac5594b1f47d1ab4f GIT binary patch literal 3433 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 IHvZTC1?$*j3IG5A literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/dsh.png b/yanzhu-ui-app/static/images/dsh.png new file mode 100644 index 0000000000000000000000000000000000000000..c071fc3f041ee7806306da72bd95ebf4f85bb5bb GIT binary patch literal 6775 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 Z@IQz&&TU+3lEDA~002ovPDHLkV1k$Q?{okF literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/img1.png b/yanzhu-ui-app/static/images/img1.png new file mode 100644 index 0000000000000000000000000000000000000000..0869cd9fab7bf12e80b4a0e8cdcfbc527e839371 GIT binary patch literal 2445 zcmV;833B#{P)Px#1am@3R0s$N2z&@+hyVZyH%UZ6RCt{2oy%?;M;3aJ^d zb+f*WC9%8M@W)ei>PiLx{I|c}#EQb+`_F&7eukJZ09efTzT_O!j-RCy3a|$^c4l99 z{T#7i^usDk=3oy-1C`9gU$W%kNoMjNR$DTEFxoj7l;kUdfz_5=fPZmg=ir;JpCc4X z!N6)u=HOq91|nH27|4=`Ah}jB&=1MQcnigN6V=J@n%6I0t4@yW$}RBujXV3_hIq!V zXcP>jFS*>FHC|Jl9O3N6)VgfW@%d=Czmkmv1L;bp=mmglx3-pl18^x~U%x!UpMNxe z5LEP8vaw(QI6d5(GKMc>Jxt2{AUk3;ObdQGtU@_M>0XkBbY?VdpXgj;s$-U?kUsTC*#ESzR^tve5We@}a7}$4Xxfx09T?`SB@B6cJ<$ptQwsPp4z z0HBOynd;=oTP^@_;QP}ABRQyGAf9BMT)COfE7<+=&g@Z;!aRv47ziV|sam#?Oz1u&K_zo`zufI!a_}lz z#J9ROX>&!Xsw!BluIYNQ994E50?zou)5E`g5~MH>q6!AwC7Z|v-VT76N>;VGqGXzK z3;|=s!^QmlkAoHH@(gXgkxg|iN^0uD&}9E&KCy0-Rb8kM8MO>!{F8F~;BoMR4Tv7W zgiRz@Cr3Cxe%2^gp4e}yuEixiy1|ebaLyi`9(EJStqBI~B>(xxtnojbR&t2wB&&pn zY;&7ntQ*O#3I^izlV88Q{6SDjmWL&6217!@7<;ss@7-(V&EC+uU?7}ix%(p`OD3q= zmj^@If^$4>Q*tMQ0e{J2LS))^mAgnJ*>$3UCO2&19FJeMB)PRLT1Tu23RRm6xG$d- z%LRaU-kmIec9~`b00wri+?oC0{4hrEkpQleb=?|St~@NMl3W*w#ds6fZt0`dXErLf zO5tv1X=RB`2Ll>#)tPkX27m1L>tvY#ww z%BsZ$O~~20_5EN!Eq>kmp#GWx(1m1iQo?nWh}aysEd2ohUg7EDP%n89f`N7=tK_;S zRBscst4n}Q;Y=@iFoFR;$)*t`4}ge~ON#+0;W9z)uDQY)p1x8@?tPM_!gcviT~$lR zIFUG;nIf_4q$>CN?Wy--K!O$QgYwSo-^=p7OH2^kNPc^OntC%hNpO)%_t!146$f5? z;T8XRaX9(M^1XwUnjkKFp@6G99pn=PT;_PGomCy=Mv+Tpx+Ys9objJuy^%b~Dq6&M z`48c%dhL~HgJs%Y z8KP@PO%p2ld=cBWdF3LQh#ARZ^=f-oi0b<$RQIXwm08IuS|pTY)s|91mQW|xw#p`S zQ)sN3aH$NR}g(ewJzK z1IuI5GPYyVIf84jJu?KT7tqwt4Y99SBqv!0gi5?jzqYL zAhqf`3ywfalC$7Qq#`*Bjz|iUv*5^dEjbHrfzj^%lyxLI3vP+BBgt8Ci*zA53vQXV zC1=4M(5B=pxFgzKTlC$7Mh$T4-PKX$iv*5%CEjbHLkdTtI z;6w=}ISWph5R$Xt#POA!1@{0S$ysnuaFv_|_XrosS#Zy=m7E3l5F5!^a8EInoCWt7 z6UkX{&uNmJ1rLBa$yx9~&`HjM2ZTy;7CbOy$yx9K>1vxyrUU*DJ96lm-i!yN00000 LNkvXXu0mjfE~=~1 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/img2.png b/yanzhu-ui-app/static/images/img2.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e5bbdef68785672f8f12471d1744e7d0e4213f GIT binary patch literal 2729 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 FV1oZq;^qJV literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/img4.png b/yanzhu-ui-app/static/images/img4.png new file mode 100644 index 0000000000000000000000000000000000000000..a718ca2d25779a190bc6961c4448d28157c6ce9d GIT binary patch literal 2870 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/img5.png b/yanzhu-ui-app/static/images/img5.png new file mode 100644 index 0000000000000000000000000000000000000000..d83e4c81dc38414f641f69a608095c67dce999fa GIT binary patch literal 2309 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 aA>RU;8Qqgm6&=C=0000!fx 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 z≺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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/images/shbh.png b/yanzhu-ui-app/static/images/shbh.png new file mode 100644 index 0000000000000000000000000000000000000000..5ce2e49ebab320f10c2dda708d5328be47c0f785 GIT binary patch literal 6855 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/index.html b/yanzhu-ui-app/static/index.html new file mode 100644 index 00000000..2e3e084f --- /dev/null +++ b/yanzhu-ui-app/static/index.html @@ -0,0 +1,24 @@ + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + + + +
+ \ No newline at end of file diff --git a/yanzhu-ui-app/static/indexTJ.png b/yanzhu-ui-app/static/indexTJ.png new file mode 100644 index 0000000000000000000000000000000000000000..8237ac49e0cbae08af9ded46e755d57d3bd59f13 GIT binary patch literal 290437 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�I7Idy?zE$`*HDO`>{C!gZ4Vy!`N^jHb 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
32TmMj@XL$1>YfBx_uEM7HzV0XAW(Mh zrR7_-T49k+4sBYRyddblMvqv668ah~Ww;t;6rb9-#mHu$G&{~21S%WLQe&Qcxc5<4 zdEj8+VDN&pd@HiC-F1GSbYP{`xZSwJ_<04%?44PJS)|zy+f?wyM#%tpG~O9*py(cr zEUi3k46PEa3aXSKtS6!%qA*Wx2O=u`N=CCs6Ya-@r!tInIl5A4THv$sDrZUe_G?$9 z({A@1lM*vtEvh(Z78_kHUgJZHSF~Tt7d8Xtegqia9#IT(8q)E)cBz7t8&a+c6=_;j zANXSR4Jt_iqMGf851U20E=&&h%EBTCr4~MIg?^DtKK$0?>L}3P_B3?7^E*_jJlL_5 z&ls%ZtUeCDPrVq~w|W@90{Bm4;l{N6`Pc1R+$b>>j9cCR=dG9whA0#KCjRvnjg|@N z|9rv!*#jU49i;z85U~H3OOir#+Yrk?3ZLJ=lN{Nl{XldN?|%_UAeuc_#-9io{#8bS zCi43HPai}O`ao_~`rm&9L6f_^Vt;>)EbSxzTP6M1&(Zm(|3Cc&A3?*LmHQ?J{2KoK z7_^7M8;~hGiQqA%7DZF{#yW7Q2TcOfr3g+NFFEo$Gh$~ zAPi3XpRYg3f2Nj5$&>DDhW)cL`@#EfcjkZj0dpu~EH-=S=+pe;kv#pKz~JBAm0R-9 zpSC2hflrT+|9NFN|Jlm^R=7-^tE*X6RaHG8>cse+>;BTG&Gw;D2H{QX}m&mu%b zM6B?*bb8t3T3z(AQmX&2jf9~8^*d3JqvK<9GAuY5#2*>S|J!wuWugJo$GB+e$npyd zqlbo+cC)`7ou0}|O8TFU&V8GiVLm@Ux8IrLeOY6b`1oaoL_uL;Q!N9^RF0N(bfOjK zm3mvX<)n#`QJdR6@YPYIA)%^&ye7Dv;i)&bww}n?9?w@@u#7_e*xJ@6mh#3MP0H~S z5l4V#@qEa6wI}l7f{u@>jt)yO$&)x6k1d^py>^^_Z$wnE@^QDVUw4_V&OvYD@!4g| zZ@2Ru=N1;78ms*UzQ*)go{4V7ckk-I++1wAQtmdL>b-1qDn5;4l9HBgpYasFTEbZ) zUp)J;ph@yXZ~QbE758R(ditWCL$luXxWE|-B#;jAFL|NMPA62-3z_m$kf7lf?=?i5 za$a~R?Rl8A*uk0x_{DVV?K>MK_;K4JoNzAjg?ivVTLWFFhVMGoUqT)c1NNMEV`F1v6dj>Yh6^cvx8=7dulreF4o$Ql9uieX^mm6*jy=Uc^rrX_;}opO7_pJ&eh_Fg ztrh;H`K%3`gzpKKmRY6HlyHs3oXZPU)y!=6xa&;nYZ;|vo~5QvaR8Y()~~frX{Njs z{#Mg*(|J9(@|cM!P=_2HG=vCs?IX)l41YP9u{>zn^-z9-GweN>#O*fu0ar}ssmNcx zH3TFjSCQ4@@}5d&7e(qbL}YPsU@={BdmVC*<%FBk+-MYQuf58k>{&cra2wwB%rWAD zaD;4xj!V#Rjbw7;PQ6y5y%$I&`@{&b=1GB(ab)d+Yk#c}8nYsFOp^T9sfc<#ZY6HQ z6hp)&wbxa7Rc)=C%{_pLYMf4uDD|$PHz_~IMbQ%N+b22HZX>su(j1OF!d|0?p<(NE=fC09P70{l2-rP(C*%tNMT@siTwhYp&j5 zhA*>8G7F0Q?bG)WX=>OZ;QsVAuQ!Z4z25cG*Q}SqxL6mPGx9Jds#IdAG0(Vn!ckC( z_~PZu4T7yRv8AJpF>p!b4Jq7mA(79qQhb}a3q=m$@iP(cEQ<^X z1S5d8%CAS#c+`@&t_N*ARfR5oKHPfy+5YOxuI1QuC6v2pYN72bVid-QL_}+7U7V9!z^z0NivvtPz#HMknk+f&}?@)Q#!ma zM=_}ldxnUInvw1^v_U1235algT)q~Lm75i#PRojcNSzU`(4h+r?+S+sxdi(R9}i0v zIKlT%Xv(N|o>0$G@YsIUM5cmrShn|8vcWXhO{T>Lk+w8`=OH&s7ZJWspbOH^?6HU> z`vvMOvx6cHpJE{vh0Pm8!=xcHGzjBQK>@ZByYHQu5E}IO8vXT zoK*d1aBFL$2L?%Tu6=LyZSK=XYc-fP;p!P0Iw>T+Ia>+OE-dVKv$R#A59xk?DO#7| z#aa@Kj2mAG$UmuP=E6jOY;J8i7GgMm8=DfCaNDVu4x`|OKi(5GaGu_zT@DWyIKrdh z9z@jN-bfS#WO2CjD1_Wjij=X$^F$|5z&#ofx^wt3Zobj^@&{4j3Eonf1ijtsw&fj)VzkL>8$o50Mcr*!vA>TteY`^0mbw8uvvLldS!aOCvs3@k%?eu~Q z^JM;Vx5Xx9B2ML!7!gVAi;*y&ulLGM!xr13eM-OAuk!AAm4!ifIGJac=>iEJ2ug@I@1V+R-0%29q>dii3<7*}phU$l10Bh<85}7=DDP zrtolZED`uB{Rk$M;zz5T(?U6TI(k#d@4OQ;sqZyEqt~8@O6BrD*m}#bthcRuSVFob zr9(;@=?-b>?ha{?F6r);R7wzOZW<({C6x~8ZlrH`7yF!jo_)^y-(T3*<(J>RV$Lzg z8gtBVbfMLlW8U4|Ih>x^+u?Ron0S>5^$?pyof`8_J>8niOH zPwAy1gvK7xIh8FG22#bZFCd3cnsR< zm98wznTc;J_8{b~U8`Y8QupU5_a&Yg0_;a9R1f{eF+N8_XkD~g9;0~vn9`=RK~DYj z&+Bmgl!oYjeJO&sU!Z@kw^z!qMGvLmatB0BY`5XxHvNxAan<7M;v-Ve&@98mey~+$ z%9#vrjR+iN*XAe9*ri(+vd!tYo=?c%+$Yp-KiIY#v(0Zwi`*nucyp&$FY`DoSf_S> zKIZ}>iY`!i746G)>jym)La9T?vk0Nl?4kx7<~tKbs;a8120j1|NB$oIeN0fru_3O% z`PQ4Za#86+&4`#oCD2}lyM@pT`rmo>8#jyM6@l59E8*mFCMF;KW5(ex{qC=~{Ckw!(xm}wFEvUi$K-cICGW6kk%v!%pQ>^u?7y)D6Nh5#pPa-Fnx6Z*4>{_G3HG#BD`G`~NP>LLOPvVj(V_Pt z(zNZYMK1st(7Za0^;kd+sS)2Q-_h!|a}aZgfXbsa_>0Y|~#S7OU1=fhlmBo(fj$YvcZpu}-B((gS= zm{6>$%()apO|<@2qo=3$jA}*3{_)&)zWO&(?e`5+<@E}b4Cdt&e-`*#qMo))$sP=1 z9mx@>HxIdrws2T%w!kyBCNkEgo2da{K93ho3#E?(OjgCJ!zze@iN)$dKckyg&n-yNyDEB`@Jad_6PqocD_S{zYVavb@L?%dn>n76zDeLwiCUc;^# z>Mg!KX;7e>VUtUdqu;o0m#^6Ga(HQt>e@=Sw3A@+yKfDLBQSeZFsIj#^^+qXc=Xl7 z>IT_73GP4TD>x4XSnm?rN8GWcM8yt2&T$h0v14Wa?mOTee{)))T`dmE0z8dJOx6Zv ztJDS_UGHQP>^l=mnS|D;K z>IrTf7Q*KxA@}_Z{Fsv%`-B#!3``J)7OaPUmt#m#*sA;@DaCS!oxRy9$-C*PMD~`D zKP>L* z(-=iHJx7i{Y8RiBakJ_-8t1Tlkfgr&l-QNvxLr+R zKepQ$(F)qn#wI3K8}30Xp#xQFmtKPdIwLo>zPr*I8swwvEr0}+4$dOAXwS-B#l!+V z%C?>4O!m`dF6oMSZj*%`7uxN=XtPafpniXP|C4N$Da{#0G{R*5)i}JLBlU~t40kts zl|ujq7FAWTmHlql#^1z~XV~ur=RDidca2z=Bn*XymC^8rAFx!mH@C33_C_`n3Pxw+ z;pZ=V`BB9p&ZfHE=koB+((`OU)ht|QC@AZYTHl67190SrIK{cp2)ei{?fLa6>KGnB zjPLKa6b1k^U7SJfmnSNJE_(A?4h%p(8x@HM^UB`eic6Uq*1ia>w#OhBwoCna$XmpP zqr`w#9Xb7EfqWizkI0Tq0*x`e&u;2vHlqm~nMhCRnR8K5k(XmESqW~hnI}L8Zc1BD z!GW8@_dV$}0OVCGTA}J15q?zse_Yl&kN0*_+zIB2$Xl&3%dyI@((TWXcs^&uq^Ku# zb((*9wsk`}BORDgirdR?@>_U;Jh)@U6BQnwqs*F}nK5%bjCz65<`@XN!Ol{II2Z4Dtn5Fyh&K0H+kh!jB(6ex8_`l42-#(nMY(?BqvC z>dL^^=(21(zM`IWc=qg>cY;KO+F9da%aO2<=(0kmnUotFMB_C z<5I}}6Gp1R^(!G6Q8!P0)uV$#p}NCj#w*^y;$J71-))dCEHM<7Ku%39*+cOJ939`w zMGxCqq2%AyW`?DVp_E?L!rH701U2q}8N2cBL1tNF=YP##+*ggua`mZ`du(BdwS!4R zLu09Q6JbA~R)m_=Iu2mM)4#$PNLP<+&^2ZV8zWt;XE6MCw{NteFgI=d-`UJbb)WWR zSr1{^AwU|5GO;2zp;4to%U=DJ^CpY?>B3R%Uzxg)7A*QO>@S07 zF4dO9=>|Mf>p7@!!2BxVsQGTQl+Nta1gGzOLp$9|sg2}wG2mt}x9+vbwg>!?-upS% z+5Pk&C9^7HXXCGTOsv%~^KS8VviWv&b0T|03LmY3SfR6LF@@-t5_5ne9yO4_TH_8sb>B=ov(_@wn)Qv zxOj`+o47XI^?fHjeeiB!Hopf0FPo=-Kl<(Q1PLUFk<@r=c zxqb70|Ezi9i~4R7;Xg6pi<#nWECQGZ36z&KXA zm{xbhi7YH}kdn_Z@4OyBpm2L#m1u_)Qk4bJ6fhCc{mDn(4`wtA9^qEQ)QmTwSz(a! zzj}jaCIk#6@EMqx&RJdvg7C&E+gex!bBliqcRSl=XJtwmLfN9?6>~qi&0tp{EwWc$ z&UDn)h1mC+3XNk6t^FH#1xUIA5CBKQp-!&VdMpoI-Il zM}SUA1X`DtQoM@)t8$yp?n@*3i%^)5#e#U@UAksArT&Uc3^as5^u)+(zOAFUucly7 z#)%xwFb@No0;>tqsyhbMu-GerXx~YLJF~ z3>gX5AV|_k*|CzOiD=_BNuuM)G(4Dzg)_f;HZ0FR^0??nNUh2aonIHgKJz zf4GY)!yGQ%8EKCkkpREbQSopm}8BA2*ysVhr^vUHaBd z!;zkyD_L|MYOUqCaC2$N6Em}q>BR|xd#lB2H??dsa0o4dAP6XpyMRgal6lZwFj9w`o|yIj4AGIk}2d%H^mmu z6Vo?AwjN5u(a=MOny`#YX1>N757R6M@6%KIFh~GyHgJ<&kW@ zf`%-CgbB!wJu;}ec$e}Ar${hAmpjak)Jy{D(ViQwYyo=X+G}7S$2elq1OhU2m>0jLl(=2 zpFe+k{)d&3NwFI_tBcM+N8X9U?yj~Ta4H&6qZA~bU?Vdn^z#Qj3-aFl!Gn7Jqmp>t zQb?oU*`q9k-DocSG60*Q#gz*O*+6(yFZF=t$J6(32OjAxy5QJX5){>j-a9YADZ!LS zAkLm(ApsiCyXx#(t5JlM?!cQL;`E=qfAW2OgG5}#q;Qnh|2d}D{hL{z84~`&H2!?u zVgC2mY{2Z*OwX82u;1y~zQo;KC#L`J2EVE|)$y=_?&Ob8VS>ls;M(n1%DJV-Sm1Bj z#@H>^*~l82FgJsD3b4DL{OZQ~JhFze_f#xe&V_DdOR{`*0plui2(t4DxzOh`qc^BX zUE#pjtGtKVxVKwe0LB-$7w5Yod3nfNWzrkDizi>P+!2R@en!7OnvLt6uMxDRHx(ls zx)T`^u$Yd;K6?HFBLOS4vJnlhgPeI{EF7UI2b-oxKZ`jtkS6QJQ{#$k2 z?r+44KT`D_kKhfoJ|su4foVpU?UzD%Ou<#+7S!fMx=-P4nT@G+8TR2}vG$&>Y~gx+ zzIZ1u+bog%% zx2R!9{+BJf_ytMN&yeaJpGY17I_kVVBqnU;yTAL$v|X0*p7}Ru^#VX4H@dQ-W1rqG zAWvZ)yvQDsU5CH<1RzBJ0(iTT!S%I`F1f6DBRqSm7cH<}K`M0GStK@_!owszBvoI? zZ@|ZxXF&Gz6#e>8OK9qL9(FdobL+U|d|VkwFyl$KQT33__|ISU-be(QLS3Kt{@HMw z4%*RUN^2{ zAKsK517$#A0 zg-K>YWN6JY_WZa{nBBECc-8= z?`80;d%_-Ra4z&ca6KSYdA+M9jZ+faGgN}mh0`T_{ zGLB5>`5&|Q#;=CNC`haC!J<*9obXc6QSNl_tO-0*ejP2`;II;rzx-+nZjUtXJu@@& zud~6Sp~=fgsRaZ$ynXFF(XV1%Fnx$+Y1MI%>)-BM&I#L@JFY+>DdP)RbsAW^PKbt@)VI=IS zW!kO3gi;b3p-Q|pBOOC9(HK$g3CFs!` zm;n)qy)B|sySMuNZPXavz;^ZX(w{zS`rC3750F+hts(I^DU=WsUS@>$wt8tT6=@Xs zWvGwO*Ryw`DEFR54;%KqDW*QQsT!=rn zVw8mT0c&V5%^d-ux7(R#vh1!sK+Qz>o6j*5Llf z3?vh{vQY8`^5!?A_Hmb9a-bnm{&*L_jB-~bTVBW(S0tjp_~OWj zzs^R6=&L#NWMpq-E1sT<>)>4@b(s0IEi~_~ zFg574*GPglN#GYgU}f4C9lTU(24~J%Xu$UI9%?U?G>Mg4hx!78l6;(>YAPR=SDkfJ zMEh6Ke9SQ3$3iy7&mwZs2lrh1_9WBs%Mkr%>Jy06W9^}6_rPoUW(ZF2DPTJP_hSgv zJ>I}WCq3ce48J#9h?N%|gIX;3!Y}maytj}im({CH*WdGZ`)tis7+C=$a6dVRo5lvk5obaBrLab5D-`rBKV|HqOy>I)PX9eH%@A`>Eg z)kYiHgiksL74MgI7fUZq>yJ_XwI2&<$)w8>DdF}i(8KMnpPUf9z2!Pr-1TZ|XyYXG zWg>&cvZuUvk#M?>xWM7n+>DAEL2mM~`c3u|>+A}al1wxVaj)sFBVdZssB}w)?U=+R z>Nl5Gc+jBnBSiV1jUWVOp>k4-8HX0n>8tSp)agj@$s{hDxTzp*qx??V+8Y08I^=YHPLn=7S1CketgDB+6Ct` z>DxOr#lg0gV0mGh?7)>YON@a4-RF%-&r(|*v!h2T%%2FQg9$NLM=$y7(G=9DwlEME z{gDuMvgGFwX#b=mb(Ynr9QZ;QFXoB-vV)lkG!{OF2o;KuNfZtvGUyu_u^RcFgfi*Y z$xKX60w(9Rl+VKiN^Ru$DYLzcCuIe;=E*0%8Lxr=Q{^RF&fPb}v>`~9FI zn(hPbpJtHzlr_4xxmxMMhFm$x3y;BD+ImsC;e_f{+vQU7r%zNz%#p~9nPBo1B@oBC zetf@hgsHue#);Lmf@A_5My}iK$!Jf~x>_9L zLiS(A;1hV>f#fxxw%2{yXB%{hqnN^I(jD|NxS47OQh~&n8_-&!HOMdCK#Gju{kn3P z3`OU~-CSm1m2S4Ad=0Q=kGt9~h_AzvnyNIaEV89aPEV(kPh(2tS@v~RbOrq6&Qbj6 z@5ulCGWdRF8Gd#3_IEC#_j@(JKcNTbnjAMe(d@=fAuq~Lag#q&e__;&*Rd6#3H9vH zZLQ2BjnIn@l=)`tOjzgO+?(L*W2-dAsNFx^hwr7TEOhUlTVdy@Ge)!COg~PV+|%_d@^gRtE-Jq&*E_b zRre~(E%!@4X6>wIh~!^v0-)Mu-9R+Ve9HD7U-E;1hQTvk&5c(vHbi$rX3$ds${q&T z@h}MXismoFa-!tQuc(Fx-j^eWrQ0z^TvoiQgz+M|ctzhJ@xroeQ^WwNk-6=sC@H$nt@kv3%9k-1 z(io#OQV0*H)*U1-iDP|2t0;Af*w$GQGJslTt1kOBD)QwM*MzRmH13xZv9y&P_sy-x zU8q3r|AEVvDy=JoM&J<(f*3^e3&a6){0L2y0;*@hwa|lNhsBQiLZRj3O#X^J z_Von_25^zG=s^orW z3rNx)|BSB}NaLpF$C0NhUOVfe3n5jU%g{1uOkJKV7hWRZcpQ}Tm4qTu`&Z4xnCpVYRtF8J8)BLU~eDZG$Ej{n}Q8BI1OaCYVI zWr%@U%(kaah!?(*0RpHtwH}Oqs}d}K@G_}G zsSxqEqWrJK$$`4g9Xqu9MPlmFnNDQx*OyR+9_F6xH*cHZ*hw5-B7+^ZyZyG_v<5v* zCvN`Z9rjX`{a~}T2fJH4KAOwytzH;@7gpz$Dr{fxW7=kozu42H)*|ln8z{RJaeq*F zLoje5roq+YB-o(DA^S)&cXV#7z6hnvi;j+lhOi-|7GTl#Jfe*M+$UKIW$5i(CJggJ zS1DN-Ax251J+JCjDK(UXOh+p!;ytbcJOc>}m?ONdr{~?3bndAS(nycnZK%BLZOB4( zTVHeT$nPt0yyMEa%c0n*{#$hktTpFw*X&QGSH6F&7a&SCGAkcHQa(zX@arCh2wm3F zkE)of5H>w2tkwUz+_It+-bO-`}j@qI`qhwMdJD+s7jq>j6EK}f7}1t(ZF3{Lpk zlK==rIsy^%16Eu;F1PsAqQ~+dWD|8HHKb?%^A*Z5gb-vFt9w(w^q*nY)PZu!GNSX) zH#lM_%e5^$D}`+D)iGa$sVqV-u3?UZHp85zo*BIY#nj>FvS7Ht3!;x;0AkC$vssT% z{7e#>DsKXol{l<3v(~vLEZv zgU80%zzBq~tT)Q+BxSG!zh@4V%=V5 zNTzpvUUHK&?l(cwbL9h%vqy^=;N@cPk05)%Im=RwMYKm$COaQr=`FT|1Dy*7nIPe$ zCW-m|e-&dm*s5|Pg5_RhFV&g8g1P5@aShPs`vBoGMwInlcXu@oWRaqyCFAAo6UqvvTEwYBDN(p0w!%Rf{&6lomr1| zRPanep^z;NNV?bPLIR+BMturM!OhM5*XNT;e(}^Q!4M)sS&EC98}LkKG;+)9@K|BFcA~$x7T%w z5}Uyx5Tj+ZG=2CI2pc62^Ay)3O5iE(YnX~vP28s%%3Im|C8m3k{6{BRDv6ociHTku zN`mp{D7)t7Jp@L+*hD8i#E$AV^8u}!!QV@z;VfwG#~GmWqUfty9*~#!bUG-@PTlB; zvhpEpe?qYv?PX2ceKs?#SeVyBUOvVe-1;=M8}3c^tGg2?Zauv(#F&KEu+?~#de!_s?F#LZ7H+#wgEjZ zvL+#pIzCi07ZGbJ;*jHf9OBjl$Hg@F04rJ*6g7vHPy$0<8EvYNH692vgFbE-eCB|C zFmC&Ll6(!2<2JcG>PGb6PVxZ7(}c~03};znjSa&0jdUa76yx;6d|Z5NZ0y8}0$hBe zC-qK8{zU zspsD#B6P60pOnVgMaQSciVDPjS& z=5&ds_&D&5*;c8iv5;+p^2Q>>;|)sqxL8_I}y_j zKbPR9$x1LVQGx#qq#2kvo^U8*$60)0SVh(9SiXGi*d4Ubtmp6?$za`?HP_!(_%?uL zpLMi9Xi+fe&u3L7PvhcaMAX^k3Nj}10O-tiP0q>@LLJQYp!{+#a?NFc$d`aw1dfb6 zf7^3YT!uR%Xye2EX|m6J>Si)iXr9+*=6-2OuI}A5IiV&BbwHvvrE1YlSCvA(^y~qHbLIBbgW)^T-yeW-x66_{!w33bwH~ z@}FB8F({U_7a(LN4Y{u$-xr8jGCQ0zXkK`QAZx;VcnA{PU_1HA0apt_i9`Iu&bdeJ z!(HQ&pG+FqE`*cXTM&z`MY;q^GK?TSs;|CkhWnjW zUs?m@CwbLIf;UCSK-=!(#kC`z;oZlx_--=k_iGf##b&pYNf)qkiYZ->J3HY9{^DI- z68s@B@O2-&8UKlAnY-N777)hdypzm1dpLVPRI+rKPY_sdAik;<@B6Ci9sCAQnM})G zZq~qkU*2Wqo4ZkezUJnx{-uYr>`tPlf(l!G_}L+sp}A+B+`MNiYtaWDCPTB^ z28mq)?)&{LP3uYfK&WGcQ?ixgvDAZX5@EM#y~P@EJruYFa0d~coC&y(*gO1kCW$Ee zXZyq7>{cGu_DN@J9UJl@n=H2OL`&sbtNesnvBxom$<^=Q zg5)MAbNA;+m_A1uezq%xjqqteZNO}BZ|7q`3v_9>FOypd(B_#V_&pxSSRd;+|ElFG z)_pq)*Z<@@L9LpSkeloWs_MaAJSA9}70yvX*V3;tD`NDa7TN!ZXN;l-D`KW;b}N(Q zc076+UOApe;YCC8Yx2_p32jYZ=1_~vQWEkdyP(V|-HpFbgy2GtfmhqF5K`4E9}hH^ zq7x!H`0*9AHfp@zIoePMoma(`9{6<20ka<^(}~p zbO9~{BX%J0&5u20xVt+WwE|5f7pk*J?Gm#{lDjlDCf#AJv30391Re{{eXDeBDkwv| zDk#wr5fL)e;IH}8Qs2bzQZAPp5bC3;m*8rz{@Dd{osdphGgk>FW7TV3gek zs@ie#4yuA>t-l%eF_+aJFxc^BZOIe+@Upj_I2l$%FN|1{B|f6e46?gk>gj>>DK zXXbO7so@G*FZ8a+^G+RduNP9pbn4-C3N&g%g0(y_SSZEnG+0)OJhsmGhk_wOVm5JQ zMDr0Ug^nHe!~9NW`Gb(JRJV~P4YouowqDAbR}XH7K3~)0-lwvJdNt|ma#InyoBC?ILGs?M2~<|;b3OnLS+Rm%wAGUT-x|ZK=)KS*WS1gc)Mz*w*}I#9 zQHk&^j(L(K z^62wJxn)MwL_{&_#d!#+k`%isamG1cECXxz1q^eE>BGJZ-p^FD5?05?nA||3uxK$B z;H@8cEQ{nA#{6&vE3c)s_c6{TPpc!Vq!>S2=3&n4Rvh@5+WK670ZI!=;6P zlQc~K!3jGaF1r5I*2Cd2Z$-8VX?ISw!95{^CgH1Fk=M6NtWk?IW`w=>RYmq1>uelX zVX>TEQ>^uoU-}h;2!=IM&*nw+`yJU*ev~l9HQ9RH=ZGoaHp@ZS_IjGD4q}~w;lX%&0a+dOAF|Ot38-+V7=EUW_oT!XKqwOawiV-!)Bt34c&-#L_9JH@J7Y1)7fK``yQA^fJ5&K8f zrRFQviiQPSAX3MlqFoDY|A%{V=973)f441TXFZJz>8iN$m-Ez+J;%Jvfu{lNS24m= z^d+4fyXWJWhYLbDlxQz?P((nZ%k>te+~bklFNmLGeo#s2dR&23x<6jvMG=#cG;n>f z#$sr-1WF`@@^G5oG29O1-QT@WI zd9x`2YzHJw&g_ImQz(lbvXaXN^w$|#ISZih;)!mb8H14rg%=vDo3JpjVp0f0_--t4e-{}47I~CeU`u}M*URl?tL2KcA49E5t(V<{rWrB~FJ1Do zaKHcNyosRClJ2;gl=rZVw}4wujq-+y3}#)V zu$P;@>N12dQkb$XRMFj%zqQnEz4vV9K6h0 z<_)f{caVqT(79<3s9ph*RWB(gCC(FM4gwJy%s~MX|Em@GAsfcfQnx$Myy<8o+=>;i zuvPXy>EpS}ZSm~B{4~!HAsOxGqWR6CW_muSMc3Nd2WR(sf_W}8ua-)UTK{_&r5LelQEc*3=CB^RSQbQ|m zR(!Qejp|=2dsh{_nzL-zksXHkaG2}os#h(`P=^c9)CE8&X-zD{3YI+-s236pd=Bcp z_#(?*r9P%=-p@U~bM>}oUXka2W5K>tY$^#h1%}9GF-r!WYV%A8`b1pcZG5BGvXe~PBQ$gVp|?pk(S+@H zJDG{752jV5SbyS=$kht)yQ)-+*enQC8GKhG>EdVrnl581P)uVsJ&2^s?H}P?iz(tD z_<7N`8ujumvWYcgs1f*P!IymPebI-K2>&?6L^wTc;-`;zwV9-NYVX0jH*Q}KDCjwp zrO}g~Wlmep!h{^Nv8H}OIV(}W){WZk8bQd{UkxHQ%5G zw4L15iI{U#>eSK-fD4*F70L@l#yyI_rFY&epyG2CK!>}IO2B4r!_9NTF9 zGo>fb?r=r=yP*i(Gb+SQyTjklaIl{sArA2-bIq1C&8$4~d=((4fxdO1qs_~s^Vv^G z1(37wMMAfE09E)yI;Z<9{GQgBxc#w!`!A#bhA*X}ZmF0fUczSfaSS|{s^DfA61~N2 z*$m#FX%Qyz5}KuALPdrK3wT&PTwWh-*fZFgrHaCzK}Yqk{oPNY4~Gb z3W||a=hNuC^R3e%RwJA(k%#NiS|I;q_NSU4E~+Y5hd3_hPJ3=On1b{i9q_dmG|k^H zf<+O*^ru6B($*m>l__uK633kgOyf>HtVXkr=UW=Qbt zVrhS{#H!}m5tQw=e%d!7V5_z7!aQBL ziO$D<>&n~-n`Sj9%c^!L@58`+i1Ca2QCD~KhXbXCEuCST+v}K%XLSLtsIzt5ST0xl z(!zu70b7Ty26gQAoO|COS4T?s-OCY5hs%}<0TX`Yn|obDS5g`Xf$kHdb?oT(+$c>S z9JJD&&8HoFxPTE`#(j|Ty=XYvf}Z8fdu%~(?*s}MP*w4!!ViA3_Nw%L!q6yUBRDr- z3Zs9~AGRTx`n;XM;GN1^zP}T{(H!WJNz+G3>HK~JYUxZXRy9ki9~e@DRL*&Tex4%| z7gIr*6dts|a_oS*-@~?=j^*~_&~8tw{4_{Q4Oi9HWF!d>I8Dwo|0^+@QS}X!Igxq- z;+ln2jjtm9Y%XDq2R5Dm(kj=>(xOSb7aZ)&ue$YbZ44R*_@msAs|SuwLAONiSHm`M z6k3=OGPuI2&?r6l^=qh1AB?mWSN&-Yw^y!NH>8t zX2j#+fQfKO=t{H`10{HPBlHaAlTZPh{B0AKzZ&Y$e_WM*cQZ7S2Sr#X4Yas~m0~_B!hx z+OD;Ax)aVY&&J#Xv1lpwQ(ow`5rj@HwFdO&V7DfHW(*CqD|tojf$MxeE`8Zbxc(`& zZ_A;1r+6P6f1z#3Oi@)M_gRZrIjKU5&?dGwTR)z1cixq%>Bl51^6yaa`3*5Qtn0W? z1uLTr$%UBlT7G0|FHg-71{TWkwdhSJ1&BA-3gSyGntPcfIX7NJY0V{hHSBpiJHatQ2 zItCtDoDRHNk=Ms9!|0))hm2LxnVu=wq6pf1ozU;nT^*dI=DbgFo8xMdm>Tt1@R|?* zOzi4^$pYy|+Z4wP%!(Q-?({`6*Y2pnZtahap8kZk8S0`hdYa)#OqCXGoAx?uVnZEW zPTFpv(b?I73aWxqDY$uQF?$hz5&P;wLDTC-;&($x%qTC5Dt{oczsB$92{F^>jf3c& z&IZJ)OO!vJZ(KUexS*wUAgRdW?*WnS-0n@!5xzyt6>~g9nj#tu&jGLiRaF|>T+g+F z9m(OMc-f5j)ec=DQT#%mZyeudM!Q-3PBcf(2`vY*li{!z%UaSpVy|T--Hv2&&beph zBQ7F>b1QTbMSe<#ypcGQ<=D>GfkaB1f!R6q>LzDfRf6{iWED0Gm5&T>BdBelptwy` z!Iere4~w$m_USCi&sbm3ETd~5U2d1s^)h_%meqjF$BeS&BJ_G+D}FTgmH*lB(thAq z)Y&*>zohLzM6&+)NXpqp9nE?c);^^{xbGg3&Yd-mEeDXI4VPz06S5Ww2YOrymFHp~ zn1|JvEhg~`MvjoDN0F5M^`c!emgVK-3U#_)GYmhtt~GcnJg40j8Noy7Jo038MefBS z+G=yazl4P$+xx|;mvR50hsk8_dlUW1))jp(qhH2|YsPPFLY@?) z3#DACmst?Ss$3|?_Up9ZcX?`$m1qo%9Jw-1(6bSvyHx`4{x^>=lBwVsl8!3$_Wtzq z4yd*{IbepokO-#X3F?Ajkyp+9R0)cX2Ps01FOM>R+;2w-nMJZz<_=W&Ivn*xn#2Xm z3?vZVwL7&U#C`EyVogviC0W0WHX$COm2YISO(D)$NGN|MGwV4KTJszb z4~9GMzEcckxRpxW`B%r7(z3IK&Djo*g9B&4jnF~*TAToj5g9Z}#!&);6Eg{xaLYm|C{aVnizRKSu_)HQ{AIlt zgKRf{bw#-mQ}Ulp1dO3|S`;OWpR=38dDUqZeKZJ}SAqr<9I}NSvyU}QBD<(122pkP zH(}60FOg>#|9tn$_=w7&aU!UpbNwy1YVFoq5JQejDl!M+8tu6Sb~>99d&^p^YDW!3 zl1bgW6(E*p=4}#zX0PJ+!+k~V61~EIu64ZL(LpOTX6#Dfeq2gMrH;bFB5Ex4x;8Zb zfKPq}7=`v7r-;G7TN1g3TMs)P?sHW$TmxnM$s|Ku&v?v9KOIi#ISR?3QMVQ>uEjK) zl`%GA(lD@YzKr_qANbQU&t#uFFvgriX>#~p4Eu#x!t|RFVj?pcKL_!`Q!iyUW{!rP zCdTEp#`kD(Ss1}V{wu`+zg!hT)^+_ib;XdC*2B-Jm5h;w^R_BLNZFH>m;aYBjJU)yXMoKJshjJ@+AKo~Ix;Bh+$Jvu`iyD&N=YFFPC7Ipue#-UjZYR9bK3;O~i4}%OOW$ju z4AK0X3sD5!C=UHN{;OX@_bVN92ilKYGWUZ@dM^u{S6PjXLiSO^kIU5xxK1O!J!%S zHA4)&xI#@%SS)C*#$*ml443J`>h2@+vAf?Ep`eyX(?ph&>G7`d(>bcyL3nLIr1SIw z{UXPjTs7&>=H>6=EQdje!{P^2!J1=gYx&mqOhHM;b`OlE85a0^zfK?eEhO3Jj~`*Y ztx>JuoX5b6bdpy>Vn!TqG#bSMJ>P6~-is|-r44PRL`M9f;UqN48eIAO><7O(Ol3;i zGs;MF5WG*@1IL=y0H7M=hV&?lMd=MK znef`?!r1&JH#(VPC9J)CZHSF@bsF0zdq9@^ak{`2%hsM&v|Y^Q!baOJ6;HR-A@7h4 ziJ4L!dcNwA6NpxA{2|)K@nG_ClW9KqYVPDNhD^Onp`tDm@vp|5TUco51KJSkcP+NIgjSX%aL+F6s$9_X_8@VX;5 z#8`*bQKDbbEt04H#rxK*s-P&bp54~$?=%q9uzt-Q5O!Vk1hiS~JmyahTD_~e*s~#B zsUWl#bq-2(DtTT}#!&s2sJq{j(FZRR+0BvD-e_?l3{*dfe6G{Q)W9T9NEw5Lx--~( z4jYJ<85>bv<6YU$1pf>QabD|fKihjcJ!I}m)vs#O%b&m}D1$*z#8wmM@^rXTw$R>M z9tF-cL)c!onX;y|z`m~DNH)&7i~swK?F9F_B_j(%ARE12YhxvcCed`n1!Dqpj-_F( zuY)gI5R~r%HRz-Uw2sS}<@piKe(=xRH;5yG8j~|vB2QXrm~#Y?czu{6-`sG8&V9kf zw*e*6<0H%Csqpr)y=;F>z8m!+13yWv(wvTO5Ci)0?@xC#_bZr()FgmIIjejlivBI7 zk{MY9E!iF!7g8?p?_yylh*TTKVS%7~Ma3`|WV~3|`>u^NnGlHdfuFTjZbjhyS!P~q zHnV{{Q^&NMn+gi`=|H=={~K6#!n3z(D46n$hD2H^ry1}wEH+`@$q*G?D!f*B9y9OM z1ko^6GRmA>ju+pFd7=4>{WJYnv34u|RYth;1D>TxCL|OsO|#g`bn+jvoe zuYs#`#Vh$nE%%o=EI-6)_7XpQ)7b622->r%$()Qan48^eZl(|Yl0vqP=tp$+yad-D z^bVf+AL5msmpINySxlyWr+av%tR7`B@_W(4aqcIt;16&zX(s&C{`IK!lC0?XJP<3c20gFU zTgm+nIu!8Z^xIUZpjjpd4o}-FL$TO*6fNwjv~R!+Mh19{Pbt#v(&(^s99%lItaXe- zIEofl9cY`Tvk`_mU7ghNf-cGzG+eIXcwBWnyX{l~uptI2b6;^86g0h=8V-z^E|YWK znCuq?B|C?f+r!Rw?FZY*2l*kc=pzvAEWD4{pkmJI*BLA=v|#OjzNtNiD(TA@x@U=u z_|r&nh|kHaXqcGNWZCDat!M{nZU%n+?VP)z%XFnA;(S`QQqTP`p{cNqPcQZkJG1>X z@DxgYcw?TV{4d_W1PqEGPl;{3+JR$D7g&YN?x*Gq-3IYQ*qLyoYb^?8MejMkHy8CS z?h2s?6VlPA-P>SIg3Ke2sQVq7Hqs_+vLtmh$pZ?~9L?W`^`L+HVICD$UTk2FoGxY* zf<=pfyz+z(KYoSNkxUC9!f(-a?;%1LGiFU8it`~Pa^Pi>1vI$o3BO4;&gyGT>4J*Q z71ujtSt3stHFg-j8-MM^ZD&BJW@9O0)@bCnY^sw?OZ6P|gEzH0xC|q9#^SPeahna7 z3<-iF1z+SVA~bpF>IOL5Wqmd3@IRS+s}O{XpZRWL8O&b*uN)EOo&Xm-Wlg7kdHJ6d zxj@(Z|FQSpk5vDE{C7jLviIH`>sZ-)Z#fbo^H9oO*|OKcv1ci(M9CqckbO8-$c_-Q zl68z@Tu<-M=llJ9Fo;#az{)o(`%-d-+KRhC zO)ct8vyg<`q#>YXy`H+wWn0~}{`T^c#VS*!IFufoLW3F6(*rzV7`K}J5BSGCmord*LY6XUxtK)953fU2jY~t)SF4V z0|jF8>MN*M8q%F7YD4>8hE~+^Hhde)bYNLw^7v9SuB6A-sn1cV;l-@=_Y-O@_{P-g z7g1w4?XokTI6i|Jw>Yo*Pxk2E?qA#1LzJiC`6ifM zLe@{(3Un9`WV3blnFU?;gDPo#9MUv?u$bCi0!-N)=J$!pH#7xemdZlmy3)70)%rc| zUUqXMuKeQFNkiW=?lD1Bma}^^T&Ec8al3}QEiLN6l4}nAZHj$v!F%nCd0mJMsZI?|8JIJc24fK+(*#Veig zZ%{l+xicd%i*ca4qsj3!V7Zi6IR3=m;w6fKqn4 zHsy&xjBG5a6_loeZO?JaP2axWP#|Wlvd-vsQLO>$!Bi|BXOWxsUypi@(J?>X&7A!} zjSR$t>|Q16Ek63uW;^B&+nwSiXMXm1YcJ#s%ik#8EA_Lu1S6TK4xbKv_>U6yr-=Zexa*ysmdoy&X%M!u(^UjaC zYsViC51o4Ep0X1kP16Mpd1B6`(u56o_tKsYikyFZ(4eJm5HqPE31hlF(5GG+L(RK! z>lKWbG@sCH}e;Tx#I zc#wf9ZOEXE^NClxVQQV^^`#sbeMxkfs-1T4t;lq!6EsvKlD16LjTt}MwW<0qs?okw z)QyCKSvOa#EnpBWM5kou|Ji8rHEt40!RQ<5u|0XC zC&d-itaxgI@A#~FZMEBCZ!zs2u;WsN6sA?2p-xOln;mc2Vvt20*%*vUKDxeVABaZ# zzR1jax#Gz}uByplKpi8>9|Kn6Qagw1E(4HL5>7o!Wmu}0-Hm9=IA;j!D4#;9rwq;l zE`FNb=_l2~MmsnE>SQ`4tdX~Gns?mEZ14BTz297yMz<$cWYcFlxPpHHW?6%koKn!kmc9xit*u$^$ti+gROo!Pi~D91caL(-<6{1v}Ti zo);Ms2-{4K*}VAd?z`1`Lys&jq<5bMFnQ%kAhdI4)?uJF-is?&Fy(?OJ_fAyiwnLxN;*cdNN z>`pmc{}$G;MIT2^+SogvRc@}B1!(r?bAmcll!Ua1lOm|*P1xxf(ebfgJxj4 z1rjb>9xLYNM73^{hmad1P~t+jWKm~Csk8y;J-77j7CBnvxjI*UG^w_RQ~!6YZwl6o zB_Z3-*b|$-n1{N%M1BMAjcX)(1)^d~O<)+l>+OW2>Bf-cG%o_V{++*_~pgZj&j@wZ-RNizLtY)LC2?X6`9KX{EP(|QW+=7?#<{n%bfuV=2(S!ryY7 z=G@H4{FtzY|NYrYgOxus`=eGh3too*giBu{kOtLw;o8$f%Jw_R#s^jyTG4jgP|Dnk z7l)m5JgWWkxhV~sdCkX%4)@FLr^!3v3=%&AjsFZdc^YWPijKyxYw1b+a7pc7_KS9G zLVo{J=uZ9jjT|R|WggKRpiA0g*6v8e50j@%f3Ly@m#isn^XE%ezn zK&z^y59Pf$R}brwVh?g6xCvktAO5)AM1@ppMn6q&Y(UZfP4$mp`z%A<}qFP))1(V)%p=Vi@6E`KEt^RP5VIA&=D zHYNc5Q-Bw~ROX!-Y>&utdy=BOmITRrxC6O9t>xy@DLYdt!%IHGtnXluU?8xzo%Nr3 z;hqBcD7Xjumdo7n)Uw059zqyY-4+ysFYeej$go6^^M1~CDGChcz%3fyjP~%lpRL(T zP|oF(OZOwoFiup9;4rxH#|QTHH>L^PdNpT5Ne^v?`{MyNIZp;!0EkqVl{}fu=(tyG*iDZyml1cxxa3>7l;*AO<1kzozB{^z=Z@wk@&UN4E00-1jPR{kJcud*Ho zGY@&9wESc}VoDXWyyrDW9fqBHNT)0uS3t$QWRX)lC?^Od6Vt&{XVykGyR^PmozG0L zL&X5B!08vVN+ErCy3V27zfwyod#)`pug%#GxHnq{M- zit^}1Ys_`&e@&z=^Mr~`lvCrsF9=lq@uBz+NL7YDv24VXm)d4$@WSXh^k@YmKe`n9 zPrK;vF=bI3Jt3m1TE#%6nQo%b?s9XgO1n+h9l0nXbKpf>ic_f$FE%SLd%Q}6S_>{R zHXjVKGn`ws6ldk6<#XS=LHb)L9Mix!<|c)7o{Wu`fexbg(97$tXk%>1LEb zG@g}1vnxHGg`xzLa0}~5^gi;>(tpCFH4 znpypGd#I&0B$aR?tz98IZ0qBMh@o<#N|RY{Hk^^$Q{iojwdxfvi{AJzM~g{5_EE?L zmm`lnY8x;yR)xke=1{v6|6N<@1;0F8D3;V%|N_KyI0vyne4;&)knKus$l zDvE(mf$*8kiu}H|LC<-wzSw1188Yi>kl;vGw6m+5=JMZJ|8ua%s2O2J#1$Rh;4XzT ze&Sqv*;H-4lhV{q=3#{nJ2;x#gnH!m-urR8!1xn082rSOMhik8KNfs5P>@KY2SM6T zq$2I&Ra&C%a>%C|nBd((=liy#`C0J(C4b0KA29aC{DFCy=k0vG1t~{r7=5p{a_*=e+bStJgnVpLB;J^drwAHtp~nsl?<7*7s4+57nh=xj79#08zX#+I>Cxk;nZ% z5%eHc)LI!im;0bd-n$R!$rfkm--*jH<_u2S2m|~%A*W~`=3-X^1(vTZ?OqTiE3oh8 z{Arqt+JDZn|8uQHwe}v^iYLyybi>UD3lTX(H^x}c2PAHSY2bPX#^;vVrx3iz(swG) zIK;S2)2n)unWVAJFN8AeG)%7b%%kBNN~SZl=G}0C7-NN<&KIK}d1CUE^ZMOxpaimv zs??`^4Hx?atF2xA{PMF?RpMzp7{>@#C@$YPQiP>B$SEm8^RCRN3HR^3^^AO_bmfY>i>`+1-8Et%&1|si@Un9L zClwF}(5&X4Y}G}WCj_l^B??plOW2rArlg$`mi^cLz>8rbiuWwYnM2*plC zsF6_6TGlv4T;Uugw~Vb?FmYd*@@UcdPOhZGjXLWC?Y&Xn=_%*Zk%S9qLAfqKoj$Jl z{vDixz4Y4WUGA4SXKRQ50r2r1 z)3jb7c)pa!{^zAIB{Jo_Hl?2zzr~hCYhbC`_VzaI7)pdf4!%{|$o#AcAhgyA z$3n2Tu~9P~t%}>YupYV;o_#9m3Yh&+O{5#snR#aWSIh=yW!^GM*+NUL{Ko(LZAbi7 zT#IPj#2xmpIC1t(9{o|nZhfqs0^_kg#*U@(1Zpij4r0jXJKFJL!tLT&AL8?EmKpng z-ly`Sr3|p3h{ZFyLCWx~`Io5~#DJIMOs|_A`bMDr)Fn7W<)wCS1UiKKvzWM1uT)v* zRX-<+j{V!CTxjwqPJ5elemwG$Y3+3sQ+jODw|+gnY>VXX90FZ5R5-3iJv)f%l_Aq; zO%I0Z6W}Nwt-WF=oLYr_lU*mV|C#$0Yfx*$U|S+!+SWv^uQM#|H=cHua-O`+^;q_t z#M_M7Dq!)MUGv(WDp(~>vy{5b@u8$>@*=>Cw~W)GXi^&kG9~|wcb}Z+&#|BOTqe6W z$ufy3@_hgOax~aVesbOmu~AzDRS;{s@ag!U(BpXsi`Uk{Vw&?Y?h+#F_v|}8| z(pS7o=?L=bVm(iO2mT=WDkti}%@axMW$Maxpsv2ieiujhxW!hJNcrezRO6UEONGfS zEnG;8Eqy=-a_fDw(y1jmW-U7Uh+xMvt~LT)r*s-2jmgn0$yq#eiiF=Y8)hjv^c1 z=AHGot`8uQZSlvxn-sJB>>IgDgd6HJ>O?*zu}e-A(>ZgKb|L(+PK-K-`u|Ghz&KWP z@o@9j%|7+Qqp#Nf$3DTe-wRf11rIL{<2Ic4qzbWUYo#CFcR-!|5{cYlxn{4y%er`D zO0yK{m!kwr9xlah^E=T_l;HBde+&u&SeIYx-mG&Zv3? zSB&F}j+S^5w3_B`*xM@+h8Ms$@<9L0oHr(-%Cu9|vLPgvTRl4&Mq+B4)4%+iFS}R& zTOYTTK+H^viJtv9PgaO4RrgcNdjSlaj%&9lujx(>m3$aTbmE%KJ`+!xc~;*YL`g6V zv{T8m#~-%%r;zWV(v0*QQQ3xybM$*)KONH@L)2Undq9Z+p0Q%7Ly?^_w_xj}_FBL~ zE5QI#Sv}j@9Gkg(?f8}jN`ovIUUg_z zJ17hXRZ}}n6JO1L+ysw7oL;P3q4<|p-koipmmwhNJ~72mxx}AZc#eJmz{kGs$ije&x54uD$x>rcHDtzriV&HNl~XSuy2nFc~)X?e>aA%=kVB67g;cH^=lwMc&>2*LPI*_i`RB!CHWE5_RGP z{VHZJoGW%}!x?4#Kq8|x{!iPx5-N+cM=+&p4J%7thcoVq z(_`ul5F$DVgV9?+HA0#c!LVBSq$;`J9?zquUxhKgX%RDg6kgx+#v!xw=;8Cx1Nd2Q zxzkLIM-9ud$Ei`NW6GN*W6{()TIsgdym`@xN6rQZoCB08D)HF^l}1RXq(@sfL)(?Q zTe3xpy!r=tPok@Q;X+_oW2CP|?pnkvtxR9A83%}*y*&Oqxs+{TPrGQ$f8nfK#d^YM z=ePM{BF+u~Lax8%Qt&q_QQnZIGJXM&&~&dU^O#3K6YrmK-9P2GlfM#XyxCucDB~S& zQ@$jlCf>$I^6CEc)aHco=0FaHcs2g@ybW3+KKvYQjm^Q$sQy@3ChtIJk~0J04!Jjp zEJB7*){=IthZ#%ZUMh&fCro&xO3E=#Zm8)JWuW@?FN$wmuoQY>OFgbIsQ6p1K9O3B zM2uyW{SBJ;ogVsU)2=5VKeoi3It9PBj8Bs_upNOK;xWz?=bGqg@ocDG^vqLqz*SS4 zezi5kD>*&D{DO$L8gNs>LnNfYb_f~I*{gYnPJ0YelTw)$kSG|tHjCfgwZqt3-RPi(OT53$bkO+Hfc*p|l4GL|Kpjt;$rXHQh{=$x*R=W6szU!&01 zC1f@C2pZ7Ay*bk_x8I@oL+}gZ)x(mbPlGZwb&2{4R~%jI-DJ+>A*rBN+UcayuRRO6 zN>`lklAFD~&$*tl%deOkm+>HfT!t5EMW8zV*}TXst^Mi-Lz(i3I6g;Q+Gn`!h_M-- z7|)e}PGuT@_(SiKXLP7m2>h+2-&tT zG1chNa_n42Nw*VhD%EOVQbb)o=v5u+I{AhxCSoVrz-czScY)xfDCc91B7L}Dw5X$a zim($W{c-^oN_qcfb6sR)^hCA(C3i6MS5#Ch- zBpCkNt=5gp%g390tp&YG{>v{mlcZVDWAB)hZIp8q_pt384o5#yu}-g*6mrhK1LdHm z@d0i7)uM|(UB{cs@A3xp4G|gjrJi3uvR{kir;>@cFC}QN&>a^AyHRS^39=(x)$uNM zfQ`OFeRg&~`l3C*r_)wYYh|0{(A8*a@u)UCpwiWccONNTlZsgu6`n6Ka*hA#;4Hck zMWTfwOONv_6=jc|Qi|_&2(^klCsFN}w zP1y*&HfMiRQj}yO6>3?xQ(R;7p~cHITKfXp@H4Wkfa_8V$~so>bUJeA$1eY3mo21q zi@l@OJQzK^yocJp#e`@UkamDAHnbm7)S_p8J9bls_A8lbg3$)4C~ z7$N&5?52;oKm6KkLb21cPVj}&o0+GaCESX0g8#d{VdOOv&7wsUd%{#LW+ethttcPc z`t?6ko4LW256{JaJpGeDu)&fF(Cw8ApU20(6@qV;hAMii!Qc}bhqtdSv zIG|`O*`goPfG*UPn$D*T*Vlr|+WggHvmzu7K0T@On8MCB`8^TYOk&8@5y6vj;#K>b zb;Gjw+mK7??nhfut!|zX@*|T)yaa~b`_oY*ekW4V$_$75JE9_qLg85bZb`>HCI+~P zL^-aRnoP|?n?1Mj>eo@CHAAWu%&MOXiH~|>XrYv)k{T}%82_K5tj{jYHaq88K){UJ z68lC2dRlmIisI9N^JSVob8d3G4LAPhI<&N8a3_C2@i7eX%mn;;7j=KnniMDy>F0eg zQ;lcWxzwvz7jjzQE9xbaz<-P^kI;^P9Q-JVI|Js~fcT#xNdf(z`8_S>fW15v4Q>)q z#%+YC7XSFG3TjehL;rOSt=7&j1mjs-=FzUYDZ$_9LblIw+uMRi;M~LK8cOmG7_;{; zBZ(}~zVt|kxpFK8BMFQa$~75hf7vPPrP3e*QDJFc{1)Vyx2fC36aLq7FJptVv-vL> z_z!e9myI+a6oYGB56X`>eI|zB=8CNsY>p1hF#1KY3x{#hJRgNW4`@0Ke+1=+tb$z; zwgTVC)fxyh<5lKj6`WqUusih{G=s`8h={rGD!W~UiCzNXinifG`BW)5(yqMHZ@qKK z@M=H~)!g^;9bB@c8VZhai;B2 z>3LNp`M2+k{!PUU6ocHob{QsXQ_{ZsNkk=mP>5EV zA?J92z4oQa({M-*%S2Wu|M)W}rXb)7s?*Y_6KsU@)G4Z`a3;j?zfvG{$PGm+*h1S)nc8^U~TSfbT^@`WooeWcNmx2@+WD$7G51*T_r%(#s z5`W!G>&ygex5r_(l8O*<_D>oU4dj{48`?UQ&@JeiL-s1#Pm6bg(=N6`aHyf+*7FQjU7V#-V9?k z=)LyMV8U~*pQJd219^T@_!`+LCGa%VSZUm^@l}!K!$na0 zRSOONxBfAVuqinEt*zV_RU;_?z%Y56RkeeCM)F&Ao4}?uaF}G@uvT7x zqB4@<_zX;(dty@VzdsAUZ{YlV*$4BQ^9VgcggKv387qhd0}TnEgYrA#9;14$4NUlq z(u>;*ui{wyK3!c}k0cgBfQ8YG+im< z?(gdJ^=j1RdH_dInB~ucl5}dK_55IS{(L69;OrNlvWr0lx__rZclTj9_M!eL7c?grT)E>iLSoQbZZ70>iET)v>36YH>q68c;~8Jz zg*2!AW1x+jA%AF9~yyg zox<_2j7DGLKpKYzu)-4$H>!L#8a4iedhr8kd`WfKL8ZPLU^pot@LY))DhR$WlXRW| zM?%wN@j83XpzLa4ncL~d>d7FizKu=q##s=6w)uV`t96T@%()ILW!-?thkDs$Wie*o8@Pxc@}EK zR1=P4)Krcmdw~975o>36GE;5qQBteL$y_yHsZ=22_P>E!-NYTuz*pt7xf;I97oPr5 zi7Z%w3BONU1E+M{YwY|VYx|kKZQ|B9XQ9IZS;&9;wU?j@Q{udUG#*4|17Ls9Dl?EU z*n@4D;Thp{c{}esLZ4JomgI^dG}Nf2+^&m51}L3>AmcGtH}3F8uPt3NiKlv$ur+1= z>EGh+Fws>|mm9{Hylvaxc`#0V)mG|(rKsEfjSF``vKm079*w$6rFW1Cf;o z=Yu#o)r+#cGsGEcEnkDGH^o52nK0v)4fUYYg#0w9W_0uc7o?>3J zGyRq&xO8M*io(+84jp@yw_(eIw!KcKRm4-s_yv2m8Mcqq<)J_%z6twWpdk>$AkihX zU|;;6+WFWe`>(fF{G`d(AQ)F3jD#b4sv2^O>Y%M+?Hufd^l`Bsc>#Rc?z#>2gnl0z z*E%h>Xlkk{H`$y0` z&0zbXc=XWMkF9L>qk4W`j%drI$cxVRU+?wwZ6Jy4$FJ+sUh^+xKTZ7jfI_2=Oe|9^ z`>8-|Z@LD`9cUE262AeVj32kamVTM%^G)m0J613mote>6Lnj1`h>JF`k!$%zuCim4 z7gL&^d-n6NZ2Y_xju?j3o#&`P@gjje1iMf3x>xi;Aozs#+#Tvrp; zwnfFcOAgr>H_5~oZ#G_%Thn{OZtvpA(1ozS_DZtPn^I7hNZo`)yW7(g{6>cBT_}pK z91MrW(hYlri_OGwLb;)`7Asd=dkZ~|IO%s` zHx43Pc$q6^fItmi8Z$hBj*^u-)`jU>Jz+_DyOUou29G3^u_z;NTCjtfBBxKbcoQFw zp$mkE@OsGs8guJ!`JGF-86rh)L(CGF$Uj;5tSQRgTQl4MbuvcG?~1!4XK|-SpW4Q$|b^%F3(|Lx!2{Pk9ed) zPjb2G(tB7xh4=QGG#oI*2-i0$5m0jbPJO{S5zs*}^jfZ*Zqp)sX?hFGiS=corR_nv zTXIAY>w0B&rcXfGF4M)vj-y^fOTt^vH-GI`1+F{2-s1}L0&f@__rMH!b*8S)Mg$dj zn6<1fMVfah+Ep#PMVGnJbFB4+;9E>8W^1%63n7&jh|OyEOYsp8{MWbhmY=B89&-!1 zoRw&(K|f{N@nNLQbKg>6G~xGWURX2#30FV_JM_cjq%47$t6~TpHm&_sHKK`k7tP?8 zmAQ;=26jJy2kws478h=4=kMq_yO`Bj;;YHLt7fX9EEWA26$pW!>|c$zvf5RcnNV>( zy_G*Uf!A2GbU&m0%ce;7=r;X?29X5*=xa_O+D-mX!E%W}Do@;xETZStmtn80;+Ki* zrM2mW<&q4b=$>$-@jHnLX-3eiu0_axVD9v%Aj)p6#sS>ANbLoskWazU3PCu?+yb&S71?9FM*nIjK zvK=7#1lXrooV||3*HJrL_KeRW&840}qvQ*ih7C<9q`wJP*;G}X;m7aRxrw-}0sRX~>yA&3fyLXeKTa z)TpmGTQT@Fqheckv#NhBKBku~1R`uMC=>k0+fHcMPSWYl(-!@}q)WZ8ZxiZeb;+y> zuuq68q3f!|jYeD?5uCIxRBpr&u+c(vRBY(&D4qQ=oFOM+lwf*-J2tNe#OCaW=F%~n zcJ)32ueshd4jR@$Y2&O}J|~!3`F1nIF{&`?0zOI4PhP)=6BJ z{%x)i4v!;?6la-@ZvvE$J^vA{K9f@E4DyyZwy=Pf6sI;rM!h^yvK6|G-j@4SbU!3z z`~_n8z&5OZ+ANo8@Qtp`Z}v|J=~V9_2@7n7xgao0QM~{m7KRZG-*o$)rnk zK+UlNyOEIBC(2DZLg3Xt-@DJGiOjOfG@}4-=coyvj|F75$VCmCsy7VguA(Ak$ zey%~ZIb7#QmGa}VuuVrcOl#6t9Ej2qb{Y?N5S5a5*IkU5q8m>U+ z52CcT$YNjlt2xi_N`m0kWms(0D-2q%(7#3oL2!!{yca@hf}uov(fuz9BJC0@JYi7`ZB>R;#HA|yNcQDwF#16(imOVUryRwFGJGqiyQ<6pF|fIT{(@??>} zk6%MdI8?)*4R$kc61wL_o@4FZ3kxQIvn@-Khwb0kTX8a2lPrlh4%^KLWV?#_<*XtQ zXK8CwXXf|76k<@s75Wx`SFxKTbP$Cp-=L{U-q2ZaOp)caC7s`*yM!Xt{zD4exU$c5 zMz$AeU*Hw;*TVZ z{abO}K_*+n6bMIhLGP?z*?JS(=G&~ zlLHV1SlZPt#|@oSfrw7xK*RbSAd$Z>_dpE&?4QYLPQaCE)$x^y7VO8es)4tquz<$m z6l!Ot(wTbm54InYVZU2-Gut<{T|4Ad^J0CKWx;=^_xcH=Sr-e=smY@pmTMQzJJb3& z1Oy11`_RY&sMF{Haf;WO&6{ks`8@}z?z?Eaapjm6l`y))F4WI}E<@t!L5n4P!zo`U z)#GI9X$oV=FkhWL`Kc0hjA!-y%@cy1{_~zXcop3Q%ZaZ23wjP8nUfa<-d&C#L7H>v z(_a7-9*oDB&-E;y_NLY5v!5>SmQt0Kl%@8f$4Yx|b`rRO9l9+!H$%S$E|uC0?Pm60 z>K&DDXbGQQ*5x}H*Dr}8$H(#;8h6h^J%|S@8jl~iPDp;GvPHyQTJq1!SP^bvdzUQA z)zI+W#eoe0_LHf4gmS&0;~f*ek}DkjVtGp}2|ll%``^c|6nKb)35>J@rQOi7q$&2ymURfPx%-k`*j89M1RZ%Jp%3Euv zN?E6SP%e&8m*=}+{qrx!RHmCHBqw&m^%?|RJ`7|ETay~;9A1rWyHCRpp9apGPH$hz zzW^0xpJ{YYaW1$c5MiXLb#*Cm<6K6>MUFa6Gk{)88lyA2b@9Bw}05`a)?t@+mw2`++AhqS)JDrLV#p}wRz8RoRUp+O@+Wg?z>j8tI4pP# zXDi=Y3W|~1Y;5H@cJ6{$%A^#I{Q*2fvlOv;X4xz+e8GMI<@I3=; zYUpraHq)ft5ZW!flw3fs5c<%$i6jbU!JC324kHaI)~ z(?K~MPtB(O#Pdfx7NmM)dx644M6n4dw+p`d>z0YOdr>1Fs1@? z^WZMxm~h@EbBDy`ukZQwM;XkZ)=q9n-IiXy()tdwmTGFTnjpc@w2T#H$X6h; zHA9!FQSV6n?)k#jU(Fxu_#$drec>tTNF7@va`3vnYB}GvPw!l3sXL*e-Gq+>Uaiq( zW0q`|LMVDAb?lA!D~3)$rsz;{F6IXdl%?5X@l}sJ*P#E_nz?27*|hcJpCo~|;sdZ; zrB~KO7|THwgHMnc(+GV^ zw*ZK*HnN*@;cMQb`g>ECREZX^o=1+~f7DLNGGU#eTe($q`CglgEA)|9OuiZpNe%At z8WQ=Odjd_)@<&Pab}uE3d;G9yl5cm1cNkWuF~YHHpX(mP_n@Bq0r&IjVvY~hFHeD* z<9vltmEAF60azbRk8$bu)Cchdd<*k8gc0|FnU zy8FFQ?&oX|Td3w&OT8wAn!+3!T;~dZo3y6;L7ZhcB?72fEk#Mi`ZTXO$PK(yw>a&x zJ=F~R>*0N~nGk?lZ3CCH6beLHf_FxQjI{8R*^G3Mn?1}v26NRM(UaqFvVW*9eg1jQ zkp5mp$`=`5!rG*CY_qlJvq5$Wbu~r$n^f7~03avJA~v;Q>^Zmmat9use1Enk zT*Gs*zhNT|)*#OxV~$U-@I-p>VcZYVjI(bv!QGVq2#tVtFM+Z{X9##+Z!5F?wCIu5 zWtwWw-~=iw+H9K-nMC&7TK9Rc*eB4h+sHdU;>rKT^!3cMz*ErjhCI(+gH0LN z?+%5Z?~S-5n6%1}2M#Ey217zsmB}jkC~`B7jyxc>H%Z%+zK(!4te7haK0 zXp=L4S0XG3WV!|<;P9u+ih}ZKo0Z+VX~il=bTzS|`DDG4PML-D7i7<<>n}){g3v5_ zMsl(o{Cz*eFSaj2MWPz_=%JQObhA69EzSb5gy)KzOM7N{l8}C`-=}|ly!Ex9Q_*QG zi1<<|28M*fN9+j%aLW0lpYG84)lR;wHrHUdKIQA5svD9}dl((d}B%d2^fs;Wa9QEg!==d9iKMoi(&IaLM$5ZjU@Xl(y?f zDrzhCN-{ws=dYxwTF?3n>h7v}<%jjOiu0-x`MC8Ne!V+J!MuS%iKpG}5+^_x+I;lV zHmv!gQY~Z;Fv7KA@Nw_3A&=z`!#VNlouaEknOgDl&BY)w=$p@G5*MEu|CXww(d~W` zJSY|KpDLlnbIcX>!tHMTtWBGLnaA(ya)v>KtoYN>T^42u@B?eVl$!O2-J2jP&+ zUcYrI303&{YIqCxgETvxe$?7qeC5tDN4IO1cw^j}=y)snmn#FCQ2#aHb+eyY=dbW&6+D=8K;f9;LUzc(pUzf2cwf&c2+t zwQP3YTtO)}KQ_iT2RrYDr!qb!D%zQ}ej)Y+C^%{!68pF#-YkdI(Z?I((f7!3bEne1 zF5*I)WT)%(9CRF%3qXH0ucI>6Ti)*Qu;KZIcNAI|;}r+s{zZ_Vi$E!V#6$ zvUneUr?K>z6l&In^x661Vb)&%zH~Kz3RDJ@qu4mrCWq8WGwL{omg(oiNhGkCllPMz8eVc(Gs^h4;MG4VI^L7q_wHH$Ub*M< zaJr28j|fQN_|bDq&x|1nZ=cRRyDrSbM9yW6;JOl9!81!-O3kNo`fQ(ayzuWo^D!sU z1Cc;M$&L0@Gm}MxAdo9(2%%!v*ziaW*Ec2xO%NqI1}Z8Ln6>6Dc{-qF&ar`JPFUJEkI z0vdF;EZd*9$`$?Na3u!Hr*U`LBi=K9%fsmqY*qmooR2Gh{_If*v`8J{xvAHs@%?9T zNGmA@5@Si*OY9fp`L(8*AA_`YQxsPw7^EQgtZ^NWN_RMW|MA#}3Syn<<0{d~(EgO% z)jYeG%9r5i?Sw6en;xPY`p3~yksGh=0pzShL5$HM*C#Td*abA~k6Z5WIVcjoKcFuF zWn7X8xAf(@%{a8)^e14O*=$^Wfyp@r!_(!dPC%JZeXpC8o)H>_u*qm)Xxv&Ud*H@&u@8+1#!!IfjR3VF47M$M~0?*=DJ3 zsSB`k9!2OIS2bW5wwRuJj>J;qm-6tXoO+@}&MXpO^haVV@F*CC%jt@AYi}5CW?tk5 zUuq$<=SZh`(w2&NTHsgTwE%TIldwoHomeqGz!O_=$!I5_)4O#y*&%%N1!`@Y#C>rr zVyiGEXPFecF*$_0Y{SywGk*>wipg% zJ0=bDZ4S(r7mx)}|I|ndKae!1qc<;*JO=pN4R)5T!Cp$hBPWYYf=cpQ;k4tD)NzXTO(OnOE(M*zid~Bk6QWNnr{|J3u{H#$)x1*z{L10Y#4u?Va*lZTg!swwt&A z{Fc^`-`+?FEBP@SLhoCm3pgqW(2`~)MKKqa2&rWW*^?fjl~C7@DdfX1!nJ`{zZX`5 z|4oiI(c1yJ)8RfFLQ?BMf$&QQz2fBVw$Imv*$DZ#oEaiuEb%FW~e(x zd1HEiJ#5Kfj{ok}mdxKxZzjH76T~fxqi!c>(L~hY2gAnQ9#xKH0?_O8dXji_C*HS6(e_ZMb)yMc|Wk0 ze<}hEEoF;z&MXBk#I{tPr&gmsQ``(XFhj`kE|>V+*driQNSlWU8)Ya3&EF*goFlG# z9r&rPF%1ivK85=LmBg1{HN=ioLp$T~`bBf$$QzSFw9~!m8ubS3@B}RxE9jkFwX_yL z7!*+R>Su)7-SLcyJ4=%ypWTFjB&u_OGxA_z@wKa5ak5esQR?rSA2R+Nl$8oo!?d%f z{4=lD@g0$l{Gpg+e)yBi96zZ)j9q3Dy2MLGQN|g-oE};`al`eQ=n5xe8wD(n*zWxO zfATIT3=X#&)IuK|eQ0|Cqk|Ot5;S_$wa<=xKC7|x6yLI4j7jx= z955fhR}MUh+MBprKkU9z% ztIcNbYc_Q3>u)f$SE(DMx-QPv8cE$=Rl?g||0$E(=kv?ETFf-F9sLC$VLe>J3^~Cg z=ZT4n*~)e|#wILddG?8M`qQ>`NlI1MQ8^^*l2*BAr2(v6E!xLPzJYi+s_@s`H)fR1 zZM2CpN|AF&yZ#B;L8NC!cG}O2!27jquB{H)p3hqWXn=C1)$B2$564i#LxD}?vl6^DYVimudcezAbE!yoW!_*`u#On ziuQ-aSbT=U%vE}P?Cljz&jo2nddkw>Otf8*ik1=6Y#jjQ;LvaEnZ!jVr7K?b>nm3% zqGQBD(dX8;(MGCpE@p=!X6_i-?5+S9k+C#5p5ce*n9O;FX6f*6Gv*%8dnNpHh&%sk z8gC6K1s=TE?AciDJ|AgRMK;p5BQ@fi%DC)+Q*BQ`{JL!R>k(R$PQ#!+1ro04>l%X{ zWXgs5qrS2PjN{2w3vcrxo7vT6XyWnm5N7LjYJgS}&JmjCRY6XwYOYN{xA1x2IDR24 z@;(10wWO&=K0cRD45(Qe`N|Z7ZcJQp`8?SIC{H&gf=VVI@~gMi>&}=RbVX`5r2OK^ z5@Q>zO*FQm0ga=mt%0YO%G0A7M0B;$fpWEavB5-`*VTZvb>H22|Jp=X80{z(^XmF8 z=)p19Ri~GJ-@cFNyot)t6GXN1OCg1E@^Co!+B*-g zCc8C@tF+JwpaJQW&&nnv?psl$-{o9U5+xB~y&Z6Va<)fbRtgj#h=a9GBnW=@; zXN@lP#tdhH%ZCpwdXU2k0gF!@ntcfZYT24#rx+BqXe7(y4Fk(79<-C5qy zszS7&B0N)%;Z$33 zG$EMgxGVLHFLa|M+pzhUJ$PT=1|a_0nr^JJl2pm`PL&$?4fTO|!4U;)V?U3rimrR! zj-y{Zma%lpQO0R~T^*7Y%Zpo}?(J1Dd4X6&)Ck3yxAQFdrB2vch=~mIO=WA_=4I=+ ze`5E}N%ejquX$%A>_M$nm!R7xu;+>44eF9141xj-Rw8P2_hL}0<4R{^@6%UyBU^~D z92Vt?>IGfSlm%c!zDcgAp4;3(Bx~O4!|Fd{mnR&DQP&i6XfEfIY)~3Q-YqsK^EU2| zy~x+-FlGvs^C=YLjLc~CG;03#fHlO06Z2%MO& zJ2BpD2l)$K-1lFL=hemtkPUKzckB{4zpW^b&2Ly2VpxeM-rlm{o#(e1Uc01VM1#-NVn-c9tQVQTVDLH@`N8C(Z6xus|@YL4om}(=S`53smq3y@dn0`9E zOW?#PDGa-4;>)Eyc$1wJ#5$Oq|&}Cp+jIYbd}fv8itvE z0IgkRF9mqf5} zvwqX-Q{R}sxfczqP^!Ld@xxm@ai57uNR5n(3i=TbV{D7vW?#{^wR)){lXy>YtI4^O zpHIKOS#a_C>*u004$g*hhw;|OcC0Sc+)gnThvDQL5e{@9MF;-YKj6_l{z1tLSt;s~Wtp|{$<=nF?D6tlI@ujUV1Pf;P1DUY< z^ez74O^WiD^l6m@eIcj)4|C^t`>v|r*_u?(8U9r)UP_-3T=2zQFd}KZ8$in^fPX}V zVV2qat8k(eXCt7L?xsGClm%QAQ0$Z-?uijSmHI-OtTCtF`wA=87-h`kELn(H%$_QD z7mRGGy#ICRQOw+XT~nGKXa9Im7hyDD&KN>*I^?K0=RBP9N|5{KY7Hbvqf;`uT3f7> z-!=1{Dsvg4IwPo9nAmbpvj#M>Oj>(jFRzIV^n7qh_9Tv>zJIf`KE{@{>1T&_QY${1 zjcYL;@gq9KFdbzHW-%p52$DKzlpcQIr{e+IrK_-1QJW)dC|>UYC7lbK$UPbzLcSzT zoMiWF8#%h;ecX+LUy#MoDn~a(0o}79CwvY*{$)Ks;TC*wYVZ>Yv*OoKs;TuR3mu_3dlN^XAh5ApgP`YWUS6#iBWS!noG@H9Z%h5>YK@ojA2TnaSW(% z}RYiQAYwr~+w_J|#EwRG25CTwZO zwO+c2;xN7fFTMj-V~fW!Y~WbY+XsKc>V%8~-QSg&m(S=rB;_bdzR+Vy%rE2lMD~FY zZBR<&_NRD|p|&iV&Zv^SPLs&93);1dBmTs<=6lI*5a`9BB!9<~;!Dms?O@LVi0gvb@$M&zW zxvHV%!W0BjP6-oBpI)jandF;zLbK@CrsmJ=J;v7^_cHi;kn;4lwaD74V*oY50?j}1 z_k_&B(Fkz_VhZpI-G}YnV9I-L08&hs=T4_Z9YXxuLWO6)=JdMX;&@cEHkEO1rT5)@g0@8d?4j;Q zIk}Hb-e%vn`#9Zz07*KZ>wsq@fc&*q_Z9W4Q-1SLb+%|c&Eys5&7ugEJ_z^>`BWaK9GVr5Eb)$bf)$gqo2LrFV1$E)ko#Dr= z7q{o-uPtie^r5?|@EH56Vaa@Yv$-k1(f*zdI*L_9T|1bTwE&ChND5wrlt)UGb9S>Y z7ZQl9O+7Akwn+DLE==oz;2`7$l9AdOzUpx4uAMf8ms=q>CvwORY`Iu;(5m{cdyD2BkvU?-esjqcDe+`ep_&5d3{`j7&)o>SFEuXnfC+JaRwx5YHi6wvhg z;R^GXu$WIqC=%5ynnerl%dMcv;WAkC-aJRe8f!k$!1+x|4Uk&LJ4>bK<&c8&@m>OY z?Ji(v+!J9kM z++OEfshiEIMWW&8vt6%sp>Lq0dy`0!q2$MGyR#Vw1;@%zhOv=im0r?^WUSbU8fjvt zqDq-{Ru}-fW%8gU=Ocj)Up!)J){~j_^E}}@{?;)ofU%v+))*B)sf-g>qePRs>T?u0 zFN1(Rjjf&)-9o0IXbksJl^{@F=RV)ux&jaPD`D%iJ1(bk9tZvn1(sV;MU!aqS|f#l zLEnY;IM+c$+|_m$zG})NZ}b~0V}>!uwWf+e_ShaWmC^*<$rIriU+Bro+%2FQQiZqL z=V@B(Zc8x$++KiZXl8FvFyE7T;v@1SvV7^c)FOT1fC

2m5^VhYEPNmr}&Mp(*IJ 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 NX{qTW->KMy{TJv}o!|ff literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/logo.png b/yanzhu-ui-app/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d9c4bfff8a4cafabd33eb8ceb4e3fde557fdf25e GIT binary patch literal 2102 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 MpL4cmSpAmx4^4%+HUIzs literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/scss/global.scss b/yanzhu-ui-app/static/scss/global.scss new file mode 100644 index 00000000..ac636bdf --- /dev/null +++ b/yanzhu-ui-app/static/scss/global.scss @@ -0,0 +1,90 @@ +.text-center { + text-align: center; +} + +.font-13 { + font-size: 13px; +} + +.font-12 { + font-size: 12px; +} + +.font-11 { + font-size: 11px; +} + +.text-grey1 { + color: #888; +} +.text-grey2 { + color: #aaa; +} + +.list-cell-arrow::before { + content: ' '; + height: 10px; + width: 10px; + border-width: 2px 2px 0 0; + border-color: #c0c0c0; + border-style: solid; + -webkit-transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); + transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); + position: absolute; + top: 50%; + margin-top: -6px; + right: 30rpx; + } + + .list-cell { + position: relative; + width: 100%; + box-sizing: border-box; + background-color: #fff; + color: #333; + padding: 26rpx 30rpx; + } + + .list-cell:first-child { + border-radius: 8rpx 8rpx 0 0; + } + + .list-cell:last-child { + border-radius: 0 0 8rpx 8rpx; + } + + .list-cell::after { + content: ''; + position: absolute; + border-bottom: 1px solid #eaeef1; + -webkit-transform: scaleY(0.5) translateZ(0); + transform: scaleY(0.5) translateZ(0); + transform-origin: 0 100%; + bottom: 0; + right: 0; + left: 0; + pointer-events: none; + } + + + .menu-list { + margin: 15px 15px; + + .menu-item-box { + width: 100%; + display: flex; + align-items: center; + + .menu-icon { + color: #007AFF; + font-size: 16px; + margin-right: 5px; + } + + .text-right { + margin-left: auto; + margin-right: 34rpx; + color: #999; + } + } + } diff --git a/yanzhu-ui-app/static/scss/index.scss b/yanzhu-ui-app/static/scss/index.scss new file mode 100644 index 00000000..975f10cc --- /dev/null +++ b/yanzhu-ui-app/static/scss/index.scss @@ -0,0 +1,8 @@ +// global +@import "./global.scss"; +// color-ui +@import "@/static/scss/colorui.css"; +// iconfont +@import "@/static/font/iconfont.css"; +// uview +@import "@/uview-ui/index.scss"; \ No newline at end of file diff --git a/yanzhu-ui-app/static/shujunull.png b/yanzhu-ui-app/static/shujunull.png new file mode 100644 index 0000000000000000000000000000000000000000..b4cf96c9aa64f13227302db26cb9592877a79ac0 GIT binary patch literal 27254 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/tabarimg/fz1.png b/yanzhu-ui-app/static/tabarimg/fz1.png new file mode 100644 index 0000000000000000000000000000000000000000..dfbbb7928e070f12dc999fca14c34ebc25ca8859 GIT binary patch literal 1166 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/upload.png b/yanzhu-ui-app/static/upload.png new file mode 100644 index 0000000000000000000000000000000000000000..3ca1b2250941a0146750e2c8b387f8233f4df78c GIT binary patch literal 1340 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD4M^IaWitX&jKx9jP7LeL$-D$|Sc;uILpXq- zh9ji|$bIJN;uumf=k1+?e$wF*M?V^$IAUzJ_P9gKkwYtwD9z5>oqy%s?(9|THoxOG zIUhVF_4~wG>=+Zw1Laog*|+`?Hqy2Vc4Sg_(q+K%@B`KfNo#p3M`KmCjm z^0lEBoj3%6adutE~LK>i-rU z_n(3J3-}t{T>AXkCVjbRFr|9Zt&{%yW!|(c`t#~d+qrMkD!i20Hs79ncF)&}rE&W| ze|&PNs@p(WDsoy@@m|xPzfvXYf?xB;`7!OicuqS~q9C-_By`%;NlU)?y*>QIr01CE zdd`R$Q&)*I=m<5oi8AqOvq*(yh3Yd@#4CzSzP@$-_xkxYh4s(lL|-%BJN>0yJI6Ai z)!{G~M6Hjdz}}Zmvax&-iKiJsIyp?%2xLSgo@#t?@o9tTE}0Fk3lgEqm&tU<#q!-q z8c2nOyiOWd-hN#jcWmte;i^t2jdN!`R99}^Tly|sMXX!>ix6*j(z{!M`2h#L^7xtd zx-4I~riybrUof9bzaIOV3r`z#Apr#RromH(FU#y#tTMdm@W$$P^yKU40b>jFz0-8& zZ9ugf+UE&6ZQKy7dbxV{%k0g^H?3PV^XgTP;J)Is3KxvU1h{jJf?;U|Z_RAPMX_)AAwa&S*FK7Lp z74ma-zYUvW-*Vbz!Sojoem;y@v02CVyS7mG(P_+KGl~?dN`SGZ$DSjY5utctgA*`L zG}#xqPiGE$QFK5I9_`2qUu0i9^D0#Tpj2brqTO$=-Pu~t|0pT)$Kry{O*&Wq&aHm+ z?bl?5Vzz>v9A8WyqmrH2bImqawR$tHTL(-g-!{$OBQ?!`lFH9br&t-gCwTaWP1?9`b(P|Q z|DsNX@0dkBrS{9dSDR$Qv%X#;`_D?1(&}2-`8?dW2lo&pPnbHC5O z^POUoowAxgOeHg9U*!~yO0}1V@)_=g99L&C*vKk3^~D|g*L5hh3-7XLAZrbv1S6uwxY~y^}dpYZCCp~|;PvtMO+BUUY$Gl7)0ZTvzPgg&ebxsLQ E0K_&{9{>OV literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/static/zip.png b/yanzhu-ui-app/static/zip.png new file mode 100644 index 0000000000000000000000000000000000000000..8445095261af1b9c0041af267438d03f49db3e55 GIT binary patch literal 1329 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD4M^IaWitX&jKx9jP7LeL$-D$|Sc;uILpXq- zh9ji|$i409;uumf=k48%e$t){$3Et(sh69i|5jPCGu^?8%Pd!k>t5^X!mQ7FBGWPr zStnMoT~6|5_e-AT-1WRGfywTTPGtJqzd!zaRhQcyjh}qdD31N9$s3bRo>$^H6sv0t zHD^~hO^m7y|2lWF({+h?|28hUxJS^@*3(P#>m!%vvwv^jYqR|Cwijm;mrq<;{?NlS za*~LOrl^d@gyV-(Btvy2vQ9o)r!|R-aTQxmaUiYt^J#%iwnk6~AzI047>AV&FvZ0~r((VEkTb8qL zdQMgE&=ybsKb<4w>W0fFluq;RnBnsFXnM7A0~fbqO7Z_Mydi;4{O=ST;^CF|jFc#u zox^clp_Ics#-h2^?8APGP-x+?b^2<-xy$bqp;Pa%Mx*y9g{9JsR zdC|E>5*#3JrT)!0oZ0dDfzJz9HxsWB=)n&)84-!i^_*E>V{>!l#daNg@hQP`@kh4{ zs+zw<^`0D-k_zJ>4&AVeYWjVV_4iC~rwf)>UhQ7>_uqA|;|Khso;Y8y%>DE8yO;g{ zf2Y%dJ~JgQT#h-e2la!b5u8V$LxBJWa)UrC+rn=VM zb-Sr<;S)UKQ?NyIb^6cR*?4h1_MK{ENDlWk2hEdw6N==llBe zRXZneD*yxbB%?M9FBMRr;?gVKg^NCi^0P#= zSzN4~pfb;ai#=LC|Il_*lX9zoLeG_|ws)R##9v-MwU13BV^>Mvq%Aw^ZzoT43sqfu z?b*Lv|4D}~n@4yr?%HN|&!+6p8@rMjOTItlXa7-odF$tp8MY60-L~N3T6^<)W2vy( z%fBTnKmNG2rR#ZZQ)~JvB%))>gTe~DWM4fbp19h literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/store/getters.js b/yanzhu-ui-app/store/getters.js new file mode 100644 index 00000000..88547941 --- /dev/null +++ b/yanzhu-ui-app/store/getters.js @@ -0,0 +1,8 @@ +const getters = { + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + roles: state => state.user.roles, + permissions: state => state.user.permissions +} +export default getters diff --git a/yanzhu-ui-app/store/index.js b/yanzhu-ui-app/store/index.js new file mode 100644 index 00000000..83a9db56 --- /dev/null +++ b/yanzhu-ui-app/store/index.js @@ -0,0 +1,15 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import user from '@/store/modules/user' +import getters from './getters' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + user + }, + getters +}) + +export default store diff --git a/yanzhu-ui-app/store/modules/user.js b/yanzhu-ui-app/store/modules/user.js new file mode 100644 index 00000000..f6668187 --- /dev/null +++ b/yanzhu-ui-app/store/modules/user.js @@ -0,0 +1,146 @@ +import config from '@/config' +import storage from '@/utils/storage' +import constant from '@/utils/constant' +import { login, logout, getInfo, getOpenIdByCode,getWxUserPhone,phoneLogin} from '@/api/login' +import { getToken, setToken, removeToken ,setOpenId} from '@/utils/auth' + +const baseUrl = config.baseUrl + +const user = { + state: { + token: getToken(), + name: storage.get(constant.name), + avatar: storage.get(constant.avatar), + roles: storage.get(constant.roles), + permissions: storage.get(constant.permissions) + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_NAME: (state, name) => { + state.name = name + storage.set(constant.name, name) + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + storage.set(constant.avatar, avatar) + }, + SET_ROLES: (state, roles) => { + state.roles = roles + storage.set(constant.roles, roles) + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + storage.set(constant.permissions, permissions) + }, + SET_USER: (state, user) => { + state.user = user + storage.set(constant.user, user) + }, + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.data + const avatar = (user == null || user.avatar == "" || user.avatar == null) ? require("@/static/images/profile.jpg") : baseUrl + user.avatar + const username = (user == null || user.userName == "" || user.userName == null) ? "" : user.userName + if (res.roles && res.roles.length > 0) { + commit('SET_ROLES', res.roles) + commit('SET_PERMISSIONS', res.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', username) + commit('SET_AVATAR', avatar) + commit('SET_USER', user) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + storage.clean() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 登录 + phoneLogin({ + commit + }, userInfo) { + return new Promise((resolve, reject) => { + phoneLogin(userInfo).then(res => { + setToken(res.data.access_token) + // console.log('phoneLogin',res.WxToken); + commit('SET_TOKEN', res.data.access_token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取phone + getWxUserPhone({ + commit + }, userInfo) { + return new Promise((resolve, reject) => { + getWxUserPhone(userInfo).then(res => { + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取openid存session + getOpenIdByCode({ + commit + }, userInfo) { + return new Promise((resolve, reject) => { + getOpenIdByCode(userInfo).then(res => { + setOpenId(res.OpenId); + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + } +} + +export default user diff --git a/yanzhu-ui-app/uni.scss b/yanzhu-ui-app/uni.scss new file mode 100644 index 00000000..f0565f1c --- /dev/null +++ b/yanzhu-ui-app/uni.scss @@ -0,0 +1,66 @@ +@import '@/uview-ui/theme.scss'; + +/** + * uni-app内置的常用样式变量 + */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#e5e5e5; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/changelog.md b/yanzhu-ui-app/uni_modules/qiun-data-charts/changelog.md new file mode 100644 index 00000000..4d470a42 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/changelog.md @@ -0,0 +1,320 @@ +## 2.5.0-20230101(2023-01-01) +- 秋云图表组件 修改条件编译顺序,确保uniapp的cli方式的项目依赖不完整时可以正常显示 +- 秋云图表组件 恢复props属性directory的使用,以修复vue3项目中,开启echarts后,echarts目录识别错误的bug +- uCharts.js 修复区域图、混合图只有一个数据时图表显示不正确的bug +- uCharts.js 修复折线图、区域图中时间轴类别图表tooltip指示点显示不正确的bug +- uCharts.js 修复x轴使用labelCount时,并且boundaryGap = 'justify' 并且关闭Y轴显示的时候,最后一个坐标值不显示的bug +- uCharts.js 修复折线图只有一组数据时 ios16 渲染颜色不正确的bug +- uCharts.js 修复玫瑰图半径显示不正确的bug +- uCharts.js 柱状图、山峰图增加正负图功能,y轴网格如果需要显示0轴则由 min max 及 splitNumber 确定,后续版本优化自动显示0轴 +- uCharts.js 柱状图column增加 opts.extra.column.labelPosition,数据标签位置,有效值为 outside外部, insideTop内顶部, center内中间, bottom内底部 +- uCharts.js 雷达图radar增加 opts.extra.radar.labelShow,否显示各项标识文案是,默认true +- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.boxPadding,提示窗边框填充距离,默认3px +- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.fontSize,提示窗字体大小配置,默认13px +- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.lineHeight,提示窗文字行高,默认20px +- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShow,是否显示左侧图例,默认true +- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShape,图例形状,图例标识样式,有效值为 auto自动跟随图例, diamond◆, circle●, triangle▲, square■, rect▬, line- +- uCharts.js 标记线markLine增加 opts.extra.markLine.labelFontSize,字体大小配置,默认13px +- uCharts.js 标记线markLine增加 opts.extra.markLine.labelPadding,标签边框内填充距离,默认6px +- uCharts.js 折线图line增加 opts.extra.line.linearType,渐变色类型,可选值 none关闭渐变色,custom 自定义渐变色。使用自定义渐变色时请赋值serie.linearColor作为颜色值 +- uCharts.js 折线图line增加 serie.linearColor,渐变色数组,格式为2维数组[起始位置,颜色值],例如[[0,'#0EE2F8'],[0.3,'#2BDCA8'],[0.6,'#1890FF'],[1,'#9A60B4']] +- uCharts.js 折线图line增加 opts.extra.line.onShadow,是否开启折线阴影,开启后请赋值serie.setShadow阴影设置 +- uCharts.js 折线图line增加 serie.setShadow,阴影配置,格式为4位数组:[offsetX,offsetY,blur,color] +- uCharts.js 折线图line增加 opts.extra.line.animation,动画效果方向,可选值为vertical 垂直动画效果,horizontal 水平动画效果 +- uCharts.js X轴xAxis增加 opts.xAxis.lineHeight,X轴字体行高,默认20px +- uCharts.js X轴xAxis增加 opts.xAxis.marginTop,X轴文字距离轴线的距离,默认0px +- uCharts.js X轴xAxis增加 opts.xAxis.title,当前X轴标题 +- uCharts.js X轴xAxis增加 opts.xAxis.titleFontSize,标题字体大小,默认13px +- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetY,标题纵向偏移距离,负数为向上偏移,正数向下偏移 +- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetX,标题横向偏移距离,负数为向左偏移,正数向右偏移 +- uCharts.js X轴xAxis增加 opts.xAxis.titleFontColor,标题字体颜色,默认#666666 + +## 报错TypeError: Cannot read properties of undefined (reading 'length') +- 如果是uni-modules版本组件,请先登录HBuilderX账号; +- 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行; +- 如果是cli项目请使用码云上的非uniCloud版本组件; +- 或者添加uniCloud的依赖; +- 或者使用原生uCharts; +## 2.4.5-20221130(2022-11-30) +- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画 +- uCharts.js 折线图修复特殊情况下只有单点数据,并改变线宽后点变为圆形的bug +- uCharts.js 修复Y轴disabled启用后无效并报错的bug +- uCharts.js 修复仪表盘起始结束角度特殊情况下显示不正确的bug +- uCharts.js 雷达图新增参数 opts.extra.radar.radius , 自定义雷达图半径 +- uCharts.js 折线图、区域图增加tooltip指示点,opts.extra.line.activeType/opts.extra.area.activeType,可选值"none"不启用激活指示点,"hollow"空心点模式,"solid"实心点模式 +## 2.4.4-20221102(2022-11-02) +- 秋云图表组件 修复使用echarts时reload、reshow无法调用重新渲染的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/40) +- 秋云图表组件 修复使用echarts时,初始化时宽高不正确的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/42) +- 秋云图表组件 修复uniapp的h5使用history模式时,无法加载echarts的bug +- 秋云图表组件 小程序端@complete、@scrollLeft、@scrollRight、@getTouchStart、@getTouchMove、@getTouchEnd事件增加opts参数传出,方便一些特殊需求的交互获取数据。 + +- uCharts.js 修复calTooltipYAxisData方法内formatter格式化方法未与y轴方法同步的问题,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/43) +- uCharts.js 地图新增参数opts.series[i].fillOpacity,以透明度方式来设置颜色过度效果,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/38) +- uCharts.js 地图新增参数opts.extra.map.active,是否启用点击激活变色 +- uCharts.js 地图新增参数opts.extra.map.activeTextColor,是否启用点击激活变色 +- uCharts.js 地图新增渲染完成事件renderComplete +- uCharts.js 漏斗图修复当部分数据相同时tooltip提示窗点击错误的bug +- uCharts.js 漏斗图新增参数series.data[i].centerText 居中标签文案 +- uCharts.js 漏斗图新增参数series.data[i].centerTextSize 居中标签文案字体大小,默认opts.fontSize +- uCharts.js 漏斗图新增参数series.data[i].centerTextColor 居中标签文案字体颜色,默认#FFFFFF +- uCharts.js 漏斗图新增参数opts.extra.funnel.minSize 最小值的最小宽度,默认0 +- uCharts.js 进度条新增参数opts.extra.arcbar.direction,动画方向,可选值为cw顺时针、ccw逆时针 +- uCharts.js 混合图新增参数opts.extra.mix.line.width,折线的宽度,默认2 +- uCharts.js 修复tooltip开启horizentalLine水平横线标注时,图表显示错位的bug +- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画 +- uCharts.js 修复开启滚动条后X轴文字超出绘图区域后的隐藏逻辑 +- uCharts.js 柱状图、条状图修复堆叠模式不能通过{value,color}赋值单个柱子颜色的问题 +- uCharts.js 气泡图修复不识别series.textSize和series.textColor的bug + +## 报错TypeError: Cannot read properties of undefined (reading 'length') +1. 如果是uni-modules版本组件,请先登录HBuilderX账号; +2. 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行; +3. 如果是cli项目请使用码云上的非uniCloud版本组件; +4. 或者添加uniCloud的依赖; +5. 或者使用原生uCharts; +## 2.4.3-20220505(2022-05-05) +- 秋云图表组件 修复开启canvas2d后将series赋值为空数组显示加载图标时,再次赋值后画布闪动的bug +- 秋云图表组件 修复升级hbx最新版后ECharts的highlight方法报错的bug +- uCharts.js 雷达图新增参数opts.extra.radar.gridEval,数据点位网格抽希,默认1 +- uCharts.js 雷达图新增参数opts.extra.radar.axisLabel, 是否显示刻度点值,默认false +- uCharts.js 雷达图新增参数opts.extra.radar.axisLabelTofix,刻度点值小数位数,默认0 +- uCharts.js 雷达图新增参数opts.extra.radar.labelPointShow,是否显示末端刻度圆点,默认false +- uCharts.js 雷达图新增参数opts.extra.radar.labelPointRadius,刻度圆点的半径,默认3 +- uCharts.js 雷达图新增参数opts.extra.radar.labelPointColor,刻度圆点的颜色,默认#cccccc +- uCharts.js 雷达图新增参数opts.extra.radar.linearType,渐变色类型,可选值"none"关闭渐变,"custom"开启渐变 +- uCharts.js 雷达图新增参数opts.extra.radar.customColor,自定义渐变颜色,数组类型对应series的数组长度以匹配不同series颜色的不同配色方案,例如["#FA7D8D", "#EB88E2"] +- uCharts.js 雷达图优化支持series.textColor、series.textSize属性 +- uCharts.js 柱状图中温度计式图标,优化支持全圆角类型,修复边框有缝隙的bug,详见官网【演示】中的温度计图表 +- uCharts.js 柱状图新增参数opts.extra.column.activeWidth,当前点击柱状图的背景宽度,默认一个单元格单位 +- uCharts.js 混合图增加opts.extra.mix.area.gradient 区域图是否开启渐变色 +- uCharts.js 混合图增加opts.extra.mix.area.opacity 区域图透明度,默认0.2 +- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelText,自定义标签文字,避免formatter格式化的繁琐,详见官网【演示】中的饼图 +- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelShow,自定义是否显示某一个指示标签,避免因饼图类别太多导致标签重复或者居多导致图形变形的问题,详见官网【演示】中的饼图 +- uCharts.js 增加opts.series[i].legendText/opts.series[0].data[i].legendText(与series.name同级)自定义图例显示文字的方法 +- uCharts.js 优化X轴、Y轴formatter格式化方法增加形参,统一为fromatter:function(value,index,opts){} +- uCharts.js 修复横屏模式下无法使用双指缩放方法的bug +- uCharts.js 修复当只有一条数据或者多条数据值相等的时候Y轴自动计算的最大值错误的bug +- 【官网模板】增加外部自定义图例与图表交互的例子,[点击跳转](https://www.ucharts.cn/v2/#/layout/info?id=2) + +## 注意:非unimodules 版本如因更新 hbx 至 3.4.7 导致报错如下,请到码云更新非 unimodules 版本组件,[点击跳转](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6) +> Error in callback for immediate watcher "uchartsOpts": "SyntaxError: Unexpected token u in JSON at position 0" +## 2.4.2-20220421(2022-04-21) +- 秋云图表组件 修复HBX升级3.4.6.20220420版本后echarts报错的问题 +## 2.4.2-20220420(2022-04-20) +## 重要!此版本uCharts新增了很多功能,修复了诸多已知问题 +- 秋云图表组件 新增onzoom开启双指缩放功能(仅uCharts),前提需要直角坐标系类图表类型,并且ontouch为true、opts.enableScroll为true,详见实例项目K线图 +- 秋云图表组件 新增optsWatch是否监听opts变化,关闭optsWatch后,动态修改opts不会触发图表重绘 +- 秋云图表组件 修复开启canvas2d功能后,动态更新数据后画布闪动的bug +- 秋云图表组件 去除directory属性,改为自动获取echarts.min.js路径(升级不受影响) +- 秋云图表组件 增加getImage()方法及@getImage事件,通过ref调用getImage()方法获,触发@getImage事件获取当前画布的base64图片文件流。 +- 秋云图表组件 支付宝、字节跳动、飞书、快手小程序支持开启canvas2d同层渲染设置。 +- 秋云图表组件 新增加【非uniCloud】版本组件,避免有些不需要uniCloud的使用组件发布至小程序需要提交隐私声明问题,请到码云[【非uniCloud版本】](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6),或npm[【非uniCloud版本】](https://www.npmjs.com/package/@qiun/uni-ucharts)下载使用。 +- uCharts.js 新增dobuleZoom双指缩放功能 +- uCharts.js 新增山峰图type="mount",数据格式为饼图类格式,不需要传入categories,具体详见新版官网在线演示 +- uCharts.js 修复折线图当数据中存在null时tooltip报错的bug +- uCharts.js 修复饼图类当画布比较小时自动计算的半径是负数报错的bug +- uCharts.js 统一各图表类型的series.formatter格式化方法的形参为(val, index, series, opts),方便格式化时有更多参数可用 +- uCharts.js 标记线功能增加labelText自定义显示文字,增加labelAlign标签显示位置(左侧或右侧),增加标签显示位置微调labelOffsetX、labelOffsetY +- uCharts.js 修复条状图当数值很小时开启圆角后样式错误的bug +- uCharts.js 修复X轴开启disabled后,X轴仍占用空间的bug +- uCharts.js 修复X轴开启滚动条并且开启rotateLabel后,X轴文字与滚动条重叠的bug +- uCharts.js 增加X轴rotateAngle文字旋转自定义角度,取值范围(-90至90) +- uCharts.js 修复地图文字标签层级显示不正确的bug +- uCharts.js 修复饼图、圆环图、玫瑰图当数据全部为0的时候不显示数据标签的bug +- uCharts.js 修复当opts.padding上边距为0时,Y轴顶部刻度标签位置不正确的bug + +## 另外我们还开发了各大原生小程序组件,已发布至码云和npm +[https://gitee.com/uCharts/uCharts](https://gitee.com/uCharts/uCharts) +[https://www.npmjs.com/~qiun](https://www.npmjs.com/~qiun) + +## 对于原生uCharts文档我们已上线新版官方网站,详情点击下面链接进入官网 +[https://www.uCharts.cn/v2/](https://www.ucharts.cn/v2/) +## 2.3.7-20220122(2022-01-22) +## 重要!使用vue3编译,请使用cli模式并升级至最新依赖,HbuilderX编译需要使用3.3.8以上版本 +- uCharts.js 修复uni-app平台组件模式使用vue3编译到小程序报错的bug。 +## 2.3.7-20220118(2022-01-18) +## 注意,使用vue3的前提是需要3.3.8.20220114-alpha版本的HBuilder! +## 2.3.67-20220118(2022-01-18) +- 秋云图表组件 组件初步支持vue3,全端编译会有些问题,具体详见下面修改: +1. 小程序端运行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new uni_modules_qiunDataCharts_js_sdk_uCharts_uCharts.uCharts,将.uCharts去掉。 +2. 小程序端发行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new e.uCharts,将.uCharts去掉,变为 new e。 +3. 如果觉得上述步骤比较麻烦,如果您的项目只编译到小程序端,可以修改u-charts.js最后一行导出方式,将 export default uCharts;变更为 export default { uCharts: uCharts }; 这样变更后,H5和App端的renderjs会有问题,请开发者自行选择。(此问题非组件问题,请等待DC官方修复Vue3的小程序端) +## 2.3.6-20220111(2022-01-11) +- 秋云图表组件 修改组件 props 属性中的 background 默认值为 rgba(0,0,0,0) +## 2.3.6-20211201(2021-12-01) +- uCharts.js 修复bar条状图开启圆角模式时,值很小时圆角渲染错误的bug +## 2.3.5-20211014(2021-10-15) +- uCharts.js 增加vue3的编译支持(仅原生uCharts,qiun-data-charts组件后续会支持,请关注更新) +## 2.3.4-20211012(2021-10-12) +- 秋云图表组件 修复 mac os x 系统 mouseover 事件丢失的 bug +## 2.3.3-20210706(2021-07-06) +- uCharts.js 增加雷达图开启数据点值(opts.dataLabel)的显示 +## 2.3.2-20210627(2021-06-27) +- 秋云图表组件 修复tooltipCustom个别情况下传值不正确报错TypeError: Cannot read property 'name' of undefined的bug +## 2.3.1-20210616(2021-06-16) +- uCharts.js 修复圆角柱状图使用4角圆角时,当数值过大时不正确的bug +## 2.3.0-20210612(2021-06-12) +- uCharts.js 【重要】uCharts增加nvue兼容,可在nvue项目中使用gcanvas组件渲染uCharts,[详见码云uCharts-demo-nvue](https://gitee.com/uCharts/uCharts) +- 秋云图表组件 增加tapLegend属性,是否开启图例点击交互事件 +- 秋云图表组件 getIndex事件中增加返回uCharts实例中的opts参数,以便在页面中调用参数 +- 示例项目 pages/other/other.vue增加app端自定义tooltip的方法,详见showOptsTooltip方法 +## 2.2.1-20210603(2021-06-03) +- uCharts.js 修复饼图、圆环图、玫瑰图,当起始角度不为0时,tooltip位置不准确的bug +- uCharts.js 增加温度计式柱状图开启顶部半圆形的配置 +## 2.2.0-20210529(2021-05-29) +- uCharts.js 增加条状图type="bar" +- 示例项目 pages/ucharts/ucharts.vue增加条状图的demo +## 2.1.7-20210524(2021-05-24) +- uCharts.js 修复大数据量模式下曲线图不平滑的bug +## 2.1.6-20210523(2021-05-23) +- 秋云图表组件 修复小程序端开启滚动条更新数据后滚动条位置不符合预期的bug +## 2.1.5-2021051702(2021-05-17) +- uCharts.js 修复自定义Y轴min和max值为0时不能正确显示的bug +## 2.1.5-20210517(2021-05-17) +- uCharts.js 修复Y轴自定义min和max时,未按指定的最大值最小值显示坐标轴刻度的bug +## 2.1.4-20210516(2021-05-16) +- 秋云图表组件 优化onWindowResize防抖方法 +- 秋云图表组件 修复APP端uCharts更新数据时,清空series显示loading图标后再显示图表,图表抖动的bug +- uCharts.js 修复开启canvas2d后,x轴、y轴、series自定义字体大小未按比例缩放的bug +- 示例项目 修复format-e.vue拼写错误导致app端使用uCharts渲染图表 +## 2.1.3-20210513(2021-05-13) +- 秋云图表组件 修改uCharts变更chartData数据为updateData方法,支持带滚动条的数据动态打点 +- 秋云图表组件 增加onWindowResize防抖方法 fix by ど誓言,如尘般染指流年づ +- 秋云图表组件 H5或者APP变更chartData数据显示loading图表时,原数据闪现的bug +- 秋云图表组件 props增加errorReload禁用错误点击重新加载的方法 +- uCharts.js 增加tooltip显示category(x轴对应点位)标题的功能,opts.extra.tooltip.showCategory,默认为false +- uCharts.js 修复mix混合图只有柱状图时,tooltip的分割线显示位置不正确的bug +- uCharts.js 修复开启滚动条,图表在拖动中动态打点,滚动条位置不正确的bug +- uCharts.js 修复饼图类数据格式为echarts数据格式,series为空数组报错的bug +- 示例项目 修改uCharts.js更新到v2.1.2版本后,@getIndex方法获取索引值变更为e.currentIndex.index +- 示例项目 pages/updata/updata.vue增加滚动条拖动更新(数据动态打点)的demo +- 示例项目 pages/other/other.vue增加errorReload禁用错误点击重新加载的demo +## 2.1.2-20210509(2021-05-09) +秋云图表组件 修复APP端初始化时就传入chartData或lacaldata不显示图表的bug +## 2.1.1-20210509(2021-05-09) +- 秋云图表组件 变更ECharts的eopts配置在renderjs内执行,支持在config-echarts.js配置文件内写function配置。 +- 秋云图表组件 修复APP端报错Prop being mutated: "onmouse"错误的bug。 +- 秋云图表组件 修复APP端报错Error: Not Found:Page[6][-1,27] at view.umd.min.js:1的bug。 +## 2.1.0-20210507(2021-05-07) +- 秋云图表组件 修复初始化时就有数据或者数据更新的时候loading加载动画闪动的bug +- uCharts.js 修复x轴format方法categories为字符串类型时返回NaN的bug +- uCharts.js 修复series.textColor、legend.fontColor未执行全局默认颜色的bug +## 2.1.0-20210506(2021-05-06) +- 秋云图表组件 修复极个别情况下报错item.properties undefined的bug +- 秋云图表组件 修复极个别情况下关闭加载动画reshow不起作用,无法显示图表的bug +- 示例项目 pages/ucharts/ucharts.vue 增加时间轴折线图(type="tline")、时间轴区域图(type="tarea")、散点图(type="scatter")、气泡图demo(type="bubble")、倒三角形漏斗图(opts.extra.funnel.type="triangle")、金字塔形漏斗图(opts.extra.funnel.type="pyramid") +- 示例项目 pages/format-u/format-u.vue 增加X轴format格式化示例 +- uCharts.js 升级至v2.1.0版本 +- uCharts.js 修复 玫瑰图面积模式点击tooltip位置不正确的bug +- uCharts.js 修复 玫瑰图点击图例,只剩一个类别显示空白的bug +- uCharts.js 修复 饼图类图点击图例,其他图表tooltip位置某些情况下不准的bug +- uCharts.js 修复 x轴为矢量轴(时间轴)情况下,点击tooltip位置不正确的bug +- uCharts.js 修复 词云图获取点击索引偶尔不准的bug +- uCharts.js 增加 直角坐标系图表X轴format格式化方法(原生uCharts.js用法请使用formatter) +- uCharts.js 增加 漏斗图扩展配置,倒三角形(opts.extra.funnel.type="triangle"),金字塔形(opts.extra.funnel.type="pyramid") +- uCharts.js 增加 散点图(opts.type="scatter")、气泡图(opts.type="bubble") +- 后期计划 完善散点图、气泡图,增加markPoints标记点,增加横向条状图。 +## 2.0.0-20210502(2021-05-02) +- uCharts.js 修复词云图获取点击索引不正确的bug +## 2.0.0-20210501(2021-05-01) +- 秋云图表组件 修复QQ小程序、百度小程序在关闭动画效果情况下,v-for循环使用图表,显示不正确的bug +## 2.0.0-20210426(2021-04-26) +- 秋云图表组件 修复QQ小程序不支持canvas2d的bug +- 秋云图表组件 修复钉钉小程序某些情况点击坐标计算错误的bug +- uCharts.js 增加 extra.column.categoryGap 参数,柱状图类每个category点位(X轴点)柱子组之间的间距 +- uCharts.js 增加 yAxis.data[i].titleOffsetY 参数,标题纵向偏移距离,负数为向上偏移,正数向下偏移 +- uCharts.js 增加 yAxis.data[i].titleOffsetX 参数,标题横向偏移距离,负数为向左偏移,正数向右偏移 +- uCharts.js 增加 extra.gauge.labelOffset 参数,仪表盘标签文字径向便宜距离,默认13px +## 2.0.0-20210422-2(2021-04-22) +秋云图表组件 修复 formatterAssign 未判断 args[key] == null 的情况导致栈溢出的 bug +## 2.0.0-20210422(2021-04-22) +- 秋云图表组件 修复H5、APP、支付宝小程序、微信小程序canvas2d模式下横屏模式的bug +## 2.0.0-20210421(2021-04-21) +- uCharts.js 修复多行图例的情况下,图例在上方或者下方时,图例float为左侧或者右侧时,第二行及以后的图例对齐方式不正确的bug +## 2.0.0-20210420(2021-04-20) +- 秋云图表组件 修复微信小程序开启canvas2d模式后,windows版微信小程序不支持canvas2d模式的bug +- 秋云图表组件 修改非uni_modules版本为v2.0版本qiun-data-charts组件 +## 2.0.0-20210419(2021-04-19) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn) +## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- uCharts.js 修复混合图中柱状图单独设置颜色不生效的bug +- uCharts.js 修复多Y轴单独设置fontSize时,开启canvas2d后,未对应放大字体的bug +## 2.0.0-20210418(2021-04-18) +- 秋云图表组件 增加directory配置,修复H5端history模式下如果发布到二级目录无法正确加载echarts.min.js的bug +## 2.0.0-20210416(2021-04-16) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn) +## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- 秋云图表组件 修复APP端某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员 +- 示例项目 修复APP端v-for循环某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员 +- uCharts.js 修复非直角坐标系tooltip提示窗右侧超出未变换方向显示的bug +## 2.0.0-20210415(2021-04-15) +- 秋云图表组件 修复H5端发布到二级目录下echarts无法加载的bug +- 秋云图表组件 修复某些情况下echarts.off('finished')移除监听事件报错的bug +## 2.0.0-20210414(2021-04-14) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn) +## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- 秋云图表组件 修复H5端在cli项目下ECharts引用地址错误的bug +- 示例项目 增加ECharts的formatter用法的示例(详见示例项目format-e.vue) +- uCharts.js 增加圆环图中心背景色的配置extra.ring.centerColor +- uCharts.js 修复微信小程序安卓端柱状图开启透明色后显示不正确的bug +## 2.0.0-20210413(2021-04-13) +- 秋云图表组件 修复百度小程序多个图表真机未能正确获取根元素dom尺寸的bug +- 秋云图表组件 修复百度小程序横屏模式方向不正确的bug +- 秋云图表组件 修改ontouch时,@getTouchStart@getTouchMove@getTouchEnd的触发条件 +- uCharts.js 修复饼图类数据格式series属性不生效的bug +- uCharts.js 增加时序区域图 详见示例项目中ucharts.vue +## 2.0.0-20210412-2(2021-04-12) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX。如仍不好用,请重启电脑,此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn) +## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- 秋云图表组件 修复uCharts在APP端横屏模式下不能正确渲染的bug +- 示例项目 增加ECharts柱状图渐变色、圆角柱状图、横向柱状图(条状图)的示例 +## 2.0.0-20210412(2021-04-12) +- 秋云图表组件 修复created中判断echarts导致APP端无法识别,改回mounted中判断echarts初始化 +- uCharts.js 修复2d模式下series.textOffset未乘像素比的bug +## 2.0.0-20210411(2021-04-11) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。 +## 初次使用如果提示未注册组件,请重启HBuilderX,并清空小程序开发者工具缓存。 +## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn) +## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- uCharts.js 折线图区域图增加connectNulls断点续连的功能,详见示例项目中ucharts.vue +- 秋云图表组件 变更初始化方法为created,变更type2d默认值为true,优化2d模式下组件初始化后dom获取不到的bug +- 秋云图表组件 修复左右布局时,右侧图表点击坐标错误的bug,修复tooltip柱状图自定义颜色显示object的bug +## 2.0.0-20210410(2021-04-10) +- 修复左右布局时,右侧图表点击坐标错误的bug,修复柱状图自定义颜色tooltip显示object的bug +- 增加标记线及柱状图自定义颜色的demo +## 2.0.0-20210409(2021-04-08) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn) +## 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +- uCharts.js 修复钉钉小程序百度小程序measureText不准确的bug,修复2d模式下饼图类activeRadius为按比例放大的bug +- 修复组件在支付宝小程序端点击位置不准确的bug +## 2.0.0-20210408(2021-04-07) +- 修复组件在支付宝小程序端不能显示的bug(目前支付宝小程不能点击交互,后续修复) +- uCharts.js 修复高分屏下柱状图类,圆弧进度条 自定义宽度不能按比例放大的bug +## 2.0.0-20210407(2021-04-06) +## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn) +## 增加 通过tofix和unit快速格式化y轴的demo add by `howcode` +## 增加 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) +## 2.0.0-20210406(2021-04-05) +# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页 +## 2.0.0(2021-04-05) +# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页 diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue new file mode 100644 index 00000000..5678f7df --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue @@ -0,0 +1,1618 @@ + + + + + + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue new file mode 100644 index 00000000..b15b19f5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue new file mode 100644 index 00000000..b7013949 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue new file mode 100644 index 00000000..7541b317 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue new file mode 100644 index 00000000..8e14db33 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue new file mode 100644 index 00000000..77c55b75 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue new file mode 100644 index 00000000..cb93a557 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue @@ -0,0 +1,229 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue new file mode 100644 index 00000000..77890607 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js new file mode 100644 index 00000000..7b8168f7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js @@ -0,0 +1,422 @@ +/* + * uCharts® + * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台 + * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved. + * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) + * 复制使用请保留本段注释,感谢支持开源! + * + * uCharts®官方网站 + * https://www.uCharts.cn + * + * 开源地址: + * https://gitee.com/uCharts/uCharts + * + * uni-app插件市场地址: + * http://ext.dcloud.net.cn/plugin?id=271 + * + */ + +// 通用配置项 + +// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性 +const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc']; + +const cfe = { + //demotype为自定义图表类型 + "type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"], + //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype" + "categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"], + //instance为实例变量承载属性,option为eopts承载属性,不要删除 + "instance": {}, + "option": {}, + //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换 + "formatter":{ + "tooltipDemo1":function(res){ + let result = '' + for (let i in res) { + if (i == 0) { + result += res[i].axisValueLabel + '年销售额' + } + let value = '--' + if (res[i].data !== null) { + value = res[i].data + } + // #ifdef H5 + result += '\n' + res[i].seriesName + ':' + value + ' 万元' + // #endif + + // #ifdef APP-PLUS + result += '
' + res[i].marker + res[i].seriesName + ':' + value + ' 万元' + // #endif + } + return result; + }, + legendFormat:function(name){ + return "自定义图例+"+name; + }, + yAxisFormatDemo:function (value, index) { + return value + '元'; + }, + seriesFormatDemo:function(res){ + return res.name + '年' + res.value + '元'; + } + }, + //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在eopts参数,会将demotype与eopts中option合并后渲染图表。 + "demotype":{ + "color": color, + //在这里填写echarts的option即可 + + }, + //下面是自定义配置,请添加项目所需的通用配置 + "column": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'axis' + }, + "grid": { + "top": 30, + "bottom": 50, + "right": 15, + "left": 40 + }, + "legend": { + "bottom": 'left', + }, + "toolbox": { + "show": false, + }, + "xAxis": { + "type": 'category', + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + "boundaryGap": true, + "data": [] + }, + "yAxis": { + "type": 'value', + "axisTick": { + "show": false, + }, + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + }, + "seriesTemplate": { + "name": '', + "type": 'bar', + "data": [], + "barwidth": 20, + "label": { + "show": true, + "color": "#666666", + "position": 'top', + }, + }, + }, + "line": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'axis' + }, + "grid": { + "top": 30, + "bottom": 50, + "right": 15, + "left": 40 + }, + "legend": { + "bottom": 'left', + }, + "toolbox": { + "show": false, + }, + "xAxis": { + "type": 'category', + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + "boundaryGap": true, + "data": [] + }, + "yAxis": { + "type": 'value', + "axisTick": { + "show": false, + }, + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + }, + "seriesTemplate": { + "name": '', + "type": 'line', + "data": [], + "barwidth": 20, + "label": { + "show": true, + "color": "#666666", + "position": 'top', + }, + }, + }, + "area": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'axis' + }, + "grid": { + "top": 30, + "bottom": 50, + "right": 15, + "left": 40 + }, + "legend": { + "bottom": 'left', + }, + "toolbox": { + "show": false, + }, + "xAxis": { + "type": 'category', + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + "boundaryGap": true, + "data": [] + }, + "yAxis": { + "type": 'value', + "axisTick": { + "show": false, + }, + "axisLabel": { + "color": '#666666' + }, + "axisLine": { + "lineStyle": { + "color": '#CCCCCC' + } + }, + }, + "seriesTemplate": { + "name": '', + "type": 'line', + "data": [], + "areaStyle": {}, + "label": { + "show": true, + "color": "#666666", + "position": 'top', + }, + }, + }, + "pie": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'item' + }, + "grid": { + "top": 40, + "bottom": 30, + "right": 15, + "left": 15 + }, + "legend": { + "bottom": 'left', + }, + "seriesTemplate": { + "name": '', + "type": 'pie', + "data": [], + "radius": '50%', + "label": { + "show": true, + "color": "#666666", + "position": 'top', + }, + }, + }, + "ring": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'item' + }, + "grid": { + "top": 40, + "bottom": 30, + "right": 15, + "left": 15 + }, + "legend": { + "bottom": 'left', + }, + "seriesTemplate": { + "name": '', + "type": 'pie', + "data": [], + "radius": ['40%', '70%'], + "avoidLabelOverlap": false, + "label": { + "show": true, + "color": "#666666", + "position": 'top', + }, + "labelLine": { + "show": true + }, + }, + }, + "rose": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'item' + }, + "legend": { + "top": 'bottom' + }, + "seriesTemplate": { + "name": '', + "type": 'pie', + "data": [], + "radius": "55%", + "center": ['50%', '50%'], + "roseType": 'area', + }, + }, + "funnel": { + "color": color, + "title": { + "text": '' + }, + "tooltip": { + "trigger": 'item', + "formatter": "{b} : {c}%" + }, + "legend": { + "top": 'bottom' + }, + "seriesTemplate": { + "name": '', + "type": 'funnel', + "left": '10%', + "top": 60, + "bottom": 60, + "width": '80%', + "min": 0, + "max": 100, + "minSize": '0%', + "maxSize": '100%', + "sort": 'descending', + "gap": 2, + "label": { + "show": true, + "position": 'inside' + }, + "labelLine": { + "length": 10, + "lineStyle": { + "width": 1, + "type": 'solid' + } + }, + "itemStyle": { + "bordercolor": '#fff', + "borderwidth": 1 + }, + "emphasis": { + "label": { + "fontSize": 20 + } + }, + "data": [], + }, + }, + "gauge": { + "color": color, + "tooltip": { + "formatter": '{a}
{b} : {c}%' + }, + "seriesTemplate": { + "name": '业务指标', + "type": 'gauge', + "detail": {"formatter": '{value}%'}, + "data": [{"value": 50, "name": '完成率'}] + }, + }, + "candle": { + "xAxis": { + "data": [] + }, + "yAxis": {}, + "color": color, + "title": { + "text": '' + }, + "dataZoom": [{ + "type": 'inside', + "xAxisIndex": [0, 1], + "start": 10, + "end": 100 + }, + { + "show": true, + "xAxisIndex": [0, 1], + "type": 'slider', + "bottom": 10, + "start": 10, + "end": 100 + } + ], + "seriesTemplate": { + "name": '', + "type": 'k', + "data": [], + }, + } +} + +export default cfe; \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js new file mode 100644 index 00000000..17b28b3b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js @@ -0,0 +1,606 @@ +/* + * uCharts® + * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台 + * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved. + * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) + * 复制使用请保留本段注释,感谢支持开源! + * + * uCharts®官方网站 + * https://www.uCharts.cn + * + * 开源地址: + * https://gitee.com/uCharts/uCharts + * + * uni-app插件市场地址: + * http://ext.dcloud.net.cn/plugin?id=271 + * + */ + +// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性 +const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc']; + +//事件转换函数,主要用作格式化x轴为时间轴,根据需求自行修改 +const formatDateTime = (timeStamp, returnType)=>{ + var date = new Date(); + date.setTime(timeStamp * 1000); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + m = m < 10 ? ('0' + m) : m; + var d = date.getDate(); + d = d < 10 ? ('0' + d) : d; + var h = date.getHours(); + h = h < 10 ? ('0' + h) : h; + var minute = date.getMinutes(); + var second = date.getSeconds(); + minute = minute < 10 ? ('0' + minute) : minute; + second = second < 10 ? ('0' + second) : second; + if(returnType == 'full'){return y + '-' + m + '-' + d + ' '+ h +':' + minute + ':' + second;} + if(returnType == 'y-m-d'){return y + '-' + m + '-' + d;} + if(returnType == 'h:m'){return h +':' + minute;} + if(returnType == 'h:m:s'){return h +':' + minute +':' + second;} + return [y, m, d, h, minute, second]; +} + +const cfu = { + //demotype为自定义图表类型,一般不需要自定义图表类型,只需要改根节点上对应的类型即可 + "type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"], + "range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"], + //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型,例如最后的"demotype" + //自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴(矢量x轴)类图表,没有categories,不需要加入categories + "categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"], + //instance为实例变量承载属性,不要删除 + "instance":{}, + //option为opts及eopts承载属性,不要删除 + "option":{}, + //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换 + "formatter":{ + "yAxisDemo1":function(val, index, opts){return val+'元'}, + "yAxisDemo2":function(val, index, opts){return val.toFixed(2)}, + "xAxisDemo1":function(val, index, opts){return val+'年';}, + "xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')}, + "seriesDemo1":function(val, index, series, opts){return val+'元'}, + "tooltipDemo1":function(item, category, index, opts){ + if(index==0){ + return '随便用'+item.data+'年' + }else{ + return '其他我没改'+item.data+'天' + } + }, + "pieDemo":function(val, index, series, opts){ + if(index !== undefined){ + return series[index].name+':'+series[index].data+'元' + } + }, + }, + //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在opts参数,会将demotype与opts中option合并后渲染图表。 + "demotype":{ + //我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置 + "type": "line", + "color": color, + "padding": [15,10,0,15], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "gridType": "dash", + "dashLength": 2, + }, + "legend": { + }, + "extra": { + "line": { + "type": "curve", + "width": 2 + }, + } + }, + //下面是自定义配置,请添加项目所需的通用配置 + "pie":{ + "type": "pie", + "color": color, + "padding": [5,5,5,5], + "extra": { + "pie": { + "activeOpacity": 0.5, + "activeRadius": 10, + "offsetAngle": 0, + "labelWidth": 15, + "border": true, + "borderWidth": 3, + "borderColor": "#FFFFFF" + }, + } + }, + "ring":{ + "type": "ring", + "color": color, + "padding": [5,5,5,5], + "rotate": false, + "dataLabel": true, + "legend": { + "show": true, + "position": "right", + "lineHeight": 25, + }, + "title": { + "name": "收益率", + "fontSize": 15, + "color": "#666666" + }, + "subtitle": { + "name": "70%", + "fontSize": 25, + "color": "#7cb5ec" + }, + "extra": { + "ring": { + "ringWidth":30, + "activeOpacity": 0.5, + "activeRadius": 10, + "offsetAngle": 0, + "labelWidth": 15, + "border": true, + "borderWidth": 3, + "borderColor": "#FFFFFF" + }, + }, + }, + "rose":{ + "type": "rose", + "color": color, + "padding": [5,5,5,5], + "legend": { + "show": true, + "position": "left", + "lineHeight": 25, + }, + "extra": { + "rose": { + "type": "area", + "minRadius": 50, + "activeOpacity": 0.5, + "activeRadius": 10, + "offsetAngle": 0, + "labelWidth": 15, + "border": false, + "borderWidth": 2, + "borderColor": "#FFFFFF" + }, + } + }, + "word":{ + "type": "word", + "color": color, + "extra": { + "word": { + "type": "normal", + "autoColors": false + } + } + }, + "funnel":{ + "type": "funnel", + "color": color, + "padding": [15,15,0,15], + "extra": { + "funnel": { + "activeOpacity": 0.3, + "activeWidth": 10, + "border": true, + "borderWidth": 2, + "borderColor": "#FFFFFF", + "fillOpacity": 1, + "labelAlign": "right" + }, + } + }, + "map":{ + "type": "map", + "color": color, + "padding": [0,0,0,0], + "dataLabel": true, + "extra": { + "map": { + "border": true, + "borderWidth": 1, + "borderColor": "#666666", + "fillOpacity": 0.6, + "activeBorderColor": "#F04864", + "activeFillColor": "#FACC14", + "activeFillOpacity": 1 + }, + } + }, + "arcbar":{ + "type": "arcbar", + "color": color, + "title": { + "name": "百分比", + "fontSize": 25, + "color": "#00FF00" + }, + "subtitle": { + "name": "默认标题", + "fontSize": 15, + "color": "#666666" + }, + "extra": { + "arcbar": { + "type": "default", + "width": 12, + "backgroundColor": "#E9E9E9", + "startAngle": 0.75, + "endAngle": 0.25, + "gap": 2 + } + } + }, + "line":{ + "type": "line", + "color": color, + "padding": [15,10,0,15], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "gridType": "dash", + "dashLength": 2, + }, + "legend": { + }, + "extra": { + "line": { + "type": "straight", + "width": 2, + "activeType": "hollow" + }, + } + }, + "tline":{ + "type": "line", + "color": color, + "padding": [15,10,0,15], + "xAxis": { + "disableGrid": false, + "boundaryGap":"justify", + }, + "yAxis": { + "gridType": "dash", + "dashLength": 2, + "data":[ + { + "min":0, + "max":80 + } + ] + }, + "legend": { + }, + "extra": { + "line": { + "type": "curve", + "width": 2, + "activeType": "hollow" + }, + } + }, + "tarea":{ + "type": "area", + "color": color, + "padding": [15,10,0,15], + "xAxis": { + "disableGrid": true, + "boundaryGap":"justify", + }, + "yAxis": { + "gridType": "dash", + "dashLength": 2, + "data":[ + { + "min":0, + "max":80 + } + ] + }, + "legend": { + }, + "extra": { + "area": { + "type": "curve", + "opacity": 0.2, + "addLine": true, + "width": 2, + "gradient": true, + "activeType": "hollow" + }, + } + }, + "column":{ + "type": "column", + "color": color, + "padding": [15,15,0,5], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "data":[{"min":0}] + }, + "legend": { + }, + "extra": { + "column": { + "type": "group", + "width": 30, + "activeBgColor": "#000000", + "activeBgOpacity": 0.08 + }, + } + }, + "mount":{ + "type": "mount", + "color": color, + "padding": [15,15,0,5], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "data":[{"min":0}] + }, + "legend": { + }, + "extra": { + "mount": { + "type": "mount", + "widthRatio": 1.5, + }, + } + }, + "bar":{ + "type": "bar", + "color": color, + "padding": [15,30,0,5], + "xAxis": { + "boundaryGap":"justify", + "disableGrid":false, + "min":0, + "axisLine":false + }, + "yAxis": { + }, + "legend": { + }, + "extra": { + "bar": { + "type": "group", + "width": 30, + "meterBorde": 1, + "meterFillColor": "#FFFFFF", + "activeBgColor": "#000000", + "activeBgOpacity": 0.08 + }, + } + }, + "area":{ + "type": "area", + "color": color, + "padding": [15,15,0,15], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "gridType": "dash", + "dashLength": 2, + }, + "legend": { + }, + "extra": { + "area": { + "type": "straight", + "opacity": 0.2, + "addLine": true, + "width": 2, + "gradient": false, + "activeType": "hollow" + }, + } + }, + "radar":{ + "type": "radar", + "color": color, + "padding": [5,5,5,5], + "dataLabel": false, + "legend": { + "show": true, + "position": "right", + "lineHeight": 25, + }, + "extra": { + "radar": { + "gridType": "radar", + "gridColor": "#CCCCCC", + "gridCount": 3, + "opacity": 0.2, + "max": 200, + "labelShow": true + }, + } + }, + "gauge":{ + "type": "gauge", + "color": color, + "title": { + "name": "66Km/H", + "fontSize": 25, + "color": "#2fc25b", + "offsetY": 50 + }, + "subtitle": { + "name": "实时速度", + "fontSize": 15, + "color": "#1890ff", + "offsetY": -50 + }, + "extra": { + "gauge": { + "type": "default", + "width": 30, + "labelColor": "#666666", + "startAngle": 0.75, + "endAngle": 0.25, + "startNumber": 0, + "endNumber": 100, + "labelFormat": "", + "splitLine": { + "fixRadius": 0, + "splitNumber": 10, + "width": 30, + "color": "#FFFFFF", + "childNumber": 5, + "childWidth": 12 + }, + "pointer": { + "width": 24, + "color": "auto" + } + } + } + }, + "candle":{ + "type": "candle", + "color": color, + "padding": [15,15,0,15], + "enableScroll": true, + "enableMarkLine": true, + "dataLabel": false, + "xAxis": { + "labelCount": 4, + "itemCount": 40, + "disableGrid": true, + "gridColor": "#CCCCCC", + "gridType": "solid", + "dashLength": 4, + "scrollShow": true, + "scrollAlign": "left", + "scrollColor": "#A6A6A6", + "scrollBackgroundColor": "#EFEBEF" + }, + "yAxis": { + }, + "legend": { + }, + "extra": { + "candle": { + "color": { + "upLine": "#f04864", + "upFill": "#f04864", + "downLine": "#2fc25b", + "downFill": "#2fc25b" + }, + "average": { + "show": true, + "name": ["MA5","MA10","MA30"], + "day": [5,10,20], + "color": ["#1890ff","#2fc25b","#facc14"] + } + }, + "markLine": { + "type": "dash", + "dashLength": 5, + "data": [ + { + "value": 2150, + "lineColor": "#f04864", + "showLabel": true + }, + { + "value": 2350, + "lineColor": "#f04864", + "showLabel": true + } + ] + } + } + }, + "mix":{ + "type": "mix", + "color": color, + "padding": [15,15,0,15], + "xAxis": { + "disableGrid": true, + }, + "yAxis": { + "disabled": false, + "disableGrid": false, + "splitNumber": 5, + "gridType": "dash", + "dashLength": 4, + "gridColor": "#CCCCCC", + "padding": 10, + "showTitle": true, + "data": [] + }, + "legend": { + }, + "extra": { + "mix": { + "column": { + "width": 20 + } + }, + } + }, + "scatter":{ + "type": "scatter", + "color":color, + "padding":[15,15,0,15], + "dataLabel":false, + "xAxis": { + "disableGrid": false, + "gridType":"dash", + "splitNumber":5, + "boundaryGap":"justify", + "min":0 + }, + "yAxis": { + "disableGrid": false, + "gridType":"dash", + }, + "legend": { + }, + "extra": { + "scatter": { + }, + } + }, + "bubble":{ + "type": "bubble", + "color":color, + "padding":[15,15,0,15], + "xAxis": { + "disableGrid": false, + "gridType":"dash", + "splitNumber":5, + "boundaryGap":"justify", + "min":0, + "max":250 + }, + "yAxis": { + "disableGrid": false, + "gridType":"dash", + "data":[{ + "min":0, + "max":150 + }] + }, + "legend": { + }, + "extra": { + "bubble": { + "border":2, + "opacity": 0.5, + }, + } + } +} + +export default cfu; \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md new file mode 100644 index 00000000..d307ba39 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md @@ -0,0 +1,5 @@ +# uCharts JSSDK说明 +1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`120kb`。 +2、如果120kb的体积仍需压缩,请手到uCharts官网通过在线定制选择您需要的图表。 +3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。 +4、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js new file mode 100644 index 00000000..f78bde5b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js @@ -0,0 +1,7706 @@ +/* + * uCharts (R) + * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台 + * Copyright (C) 2018-2022 QIUN (R) 秋云 https://www.ucharts.cn All rights reserved. + * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) + * 复制使用请保留本段注释,感谢支持开源! + * + * uCharts (R) 官方网站 + * https://www.uCharts.cn + * + * 开源地址: + * https://gitee.com/uCharts/uCharts + * + * uni-app插件市场地址: + * http://ext.dcloud.net.cn/plugin?id=271 + * + */ + +'use strict'; + +var config = { + version: 'v2.5.0-20230101', + yAxisWidth: 15, + xAxisHeight: 22, + padding: [10, 10, 10, 10], + rotate: false, + fontSize: 13, + fontColor: '#666666', + dataPointShape: ['circle', 'circle', 'circle', 'circle'], + color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'], + linearColor: ['#0EE2F8', '#2BDCA8', '#FA7D8D', '#EB88E2', '#2AE3A0', '#0EE2F8', '#EB88E2', '#6773E3', '#F78A85'], + pieChartLinePadding: 15, + pieChartTextPadding: 5, + titleFontSize: 20, + subtitleFontSize: 15, + radarLabelTextMargin: 13, +}; + +var assign = function(target, ...varArgs) { + if (target == null) { + throw new TypeError('[uCharts] Cannot convert undefined or null to object'); + } + if (!varArgs || varArgs.length <= 0) { + return target; + } + // 深度合并对象 + function deepAssign(obj1, obj2) { + for (let key in obj2) { + obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ? + deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key]; + } + return obj1; + } + varArgs.forEach(val => { + target = deepAssign(target, val); + }); + return target; +}; + +var util = { + toFixed: function toFixed(num, limit) { + limit = limit || 2; + if (this.isFloat(num)) { + num = num.toFixed(limit); + } + return num; + }, + isFloat: function isFloat(num) { + return num % 1 !== 0; + }, + approximatelyEqual: function approximatelyEqual(num1, num2) { + return Math.abs(num1 - num2) < 1e-10; + }, + isSameSign: function isSameSign(num1, num2) { + return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2; + }, + isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) { + return this.isSameSign(p1.x, p2.x); + }, + isCollision: function isCollision(obj1, obj2) { + obj1.end = {}; + obj1.end.x = obj1.start.x + obj1.width; + obj1.end.y = obj1.start.y - obj1.height; + obj2.end = {}; + obj2.end.x = obj2.start.x + obj2.width; + obj2.end.y = obj2.start.y - obj2.height; + var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y; + return !flag; + } +}; + +//兼容H5点击事件 +function getH5Offset(e) { + e.mp = { + changedTouches: [] + }; + e.mp.changedTouches.push({ + x: e.offsetX, + y: e.offsetY + }); + return e; +} + +// hex 转 rgba +function hexToRgb(hexValue, opc) { + var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + var hex = hexValue.replace(rgx, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + var r = parseInt(rgb[1], 16); + var g = parseInt(rgb[2], 16); + var b = parseInt(rgb[3], 16); + return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')'; +} + +function findRange(num, type, limit) { + if (isNaN(num)) { + throw new Error('[uCharts] series数据需为Number格式'); + } + limit = limit || 10; + type = type ? type : 'upper'; + var multiple = 1; + while (limit < 1) { + limit *= 10; + multiple *= 10; + } + if (type === 'upper') { + num = Math.ceil(num * multiple); + } else { + num = Math.floor(num * multiple); + } + while (num % limit !== 0) { + if (type === 'upper') { + if (num == num + 1) { //修复数据值过大num++无效的bug by 向日葵 @xrk_jy + break; + } + num++; + } else { + num--; + } + } + return num / multiple; +} + +function calCandleMA(dayArr, nameArr, colorArr, kdata) { + let seriesTemp = []; + for (let k = 0; k < dayArr.length; k++) { + let seriesItem = { + data: [], + name: nameArr[k], + color: colorArr[k] + }; + for (let i = 0, len = kdata.length; i < len; i++) { + if (i < dayArr[k]) { + seriesItem.data.push(null); + continue; + } + let sum = 0; + for (let j = 0; j < dayArr[k]; j++) { + sum += kdata[i - j][1]; + } + seriesItem.data.push(+(sum / dayArr[k]).toFixed(3)); + } + seriesTemp.push(seriesItem); + } + return seriesTemp; +} + +function calValidDistance(self, distance, chartData, config, opts) { + var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3]; + var dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length - 1); + if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){ + if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2 + dataChartWidth += (opts.extra.mount.widthRatio - 1)*chartData.eachSpacing; + } + var validDistance = distance; + if (distance >= 0) { + validDistance = 0; + self.uevent.trigger('scrollLeft'); + self.scrollOption.position = 'left' + opts.xAxis.scrollPosition = 'left'; + } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) { + validDistance = dataChartAreaWidth - dataChartWidth; + self.uevent.trigger('scrollRight'); + self.scrollOption.position = 'right' + opts.xAxis.scrollPosition = 'right'; + } else { + self.scrollOption.position = distance + opts.xAxis.scrollPosition = distance; + } + return validDistance; +} + +function isInAngleRange(angle, startAngle, endAngle) { + function adjust(angle) { + while (angle < 0) { + angle += 2 * Math.PI; + } + while (angle > 2 * Math.PI) { + angle -= 2 * Math.PI; + } + return angle; + } + angle = adjust(angle); + startAngle = adjust(startAngle); + endAngle = adjust(endAngle); + if (startAngle > endAngle) { + endAngle += 2 * Math.PI; + if (angle < startAngle) { + angle += 2 * Math.PI; + } + } + return angle >= startAngle && angle <= endAngle; +} + +function createCurveControlPoints(points, i) { + function isNotMiddlePoint(points, i) { + if (points[i - 1] && points[i + 1]) { + return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y, + points[i + 1].y); + } else { + return false; + } + } + function isNotMiddlePointX(points, i) { + if (points[i - 1] && points[i + 1]) { + return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x, + points[i + 1].x); + } else { + return false; + } + } + var a = 0.2; + var b = 0.2; + var pAx = null; + var pAy = null; + var pBx = null; + var pBy = null; + if (i < 1) { + pAx = points[0].x + (points[1].x - points[0].x) * a; + pAy = points[0].y + (points[1].y - points[0].y) * a; + } else { + pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a; + pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a; + } + + if (i > points.length - 3) { + var last = points.length - 1; + pBx = points[last].x - (points[last].x - points[last - 1].x) * b; + pBy = points[last].y - (points[last].y - points[last - 1].y) * b; + } else { + pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b; + pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b; + } + if (isNotMiddlePoint(points, i + 1)) { + pBy = points[i + 1].y; + } + if (isNotMiddlePoint(points, i)) { + pAy = points[i].y; + } + if (isNotMiddlePointX(points, i + 1)) { + pBx = points[i + 1].x; + } + if (isNotMiddlePointX(points, i)) { + pAx = points[i].x; + } + if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) { + pAy = points[i].y; + } + if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) { + pBy = points[i + 1].y; + } + if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) { + pAx = points[i].x; + } + if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) { + pBx = points[i + 1].x; + } + return { + ctrA: { + x: pAx, + y: pAy + }, + ctrB: { + x: pBx, + y: pBy + } + }; +} + + +function convertCoordinateOrigin(x, y, center) { + return { + x: center.x + x, + y: center.y - y + }; +} + +function avoidCollision(obj, target) { + if (target) { + // is collision test + while (util.isCollision(obj, target)) { + if (obj.start.x > 0) { + obj.start.y--; + } else if (obj.start.x < 0) { + obj.start.y++; + } else { + if (obj.start.y > 0) { + obj.start.y++; + } else { + obj.start.y--; + } + } + } + } + return obj; +} + +function fixPieSeries(series, opts, config){ + let pieSeriesArr = []; + if(series.length>0 && series[0].data.constructor.toString().indexOf('Array') > -1){ + opts._pieSeries_ = series; + let oldseries = series[0].data; + for (var i = 0; i < oldseries.length; i++) { + oldseries[i].formatter = series[0].formatter; + oldseries[i].data = oldseries[i].value; + pieSeriesArr.push(oldseries[i]); + } + opts.series = pieSeriesArr; + }else{ + pieSeriesArr = series; + } + return pieSeriesArr; +} + +function fillSeries(series, opts, config) { + var index = 0; + for (var i = 0; i < series.length; i++) { + let item = series[i]; + if (!item.color) { + item.color = config.color[index]; + index = (index + 1) % config.color.length; + } + if (!item.linearIndex) { + item.linearIndex = i; + } + if (!item.index) { + item.index = 0; + } + if (!item.type) { + item.type = opts.type; + } + if (typeof item.show == "undefined") { + item.show = true; + } + if (!item.type) { + item.type = opts.type; + } + if (!item.pointShape) { + item.pointShape = "circle"; + } + if (!item.legendShape) { + switch (item.type) { + case 'line': + item.legendShape = "line"; + break; + case 'column': + case 'bar': + item.legendShape = "rect"; + break; + case 'area': + case 'mount': + item.legendShape = "triangle"; + break; + default: + item.legendShape = "circle"; + } + } + } + return series; +} + +function fillCustomColor(linearType, customColor, series, config) { + var newcolor = customColor || []; + if (linearType == 'custom' && newcolor.length == 0 ) { + newcolor = config.linearColor; + } + if (linearType == 'custom' && newcolor.length < series.length) { + let chazhi = series.length - newcolor.length; + for (var i = 0; i < chazhi; i++) { + newcolor.push(config.linearColor[(i + 1) % config.linearColor.length]); + } + } + return newcolor; +} + +function getDataRange(minData, maxData) { + var limit = 0; + var range = maxData - minData; + if (range >= 10000) { + limit = 1000; + } else if (range >= 1000) { + limit = 100; + } else if (range >= 100) { + limit = 10; + } else if (range >= 10) { + limit = 5; + } else if (range >= 1) { + limit = 1; + } else if (range >= 0.1) { + limit = 0.1; + } else if (range >= 0.01) { + limit = 0.01; + } else if (range >= 0.001) { + limit = 0.001; + } else if (range >= 0.0001) { + limit = 0.0001; + } else if (range >= 0.00001) { + limit = 0.00001; + } else { + limit = 0.000001; + } + return { + minRange: findRange(minData, 'lower', limit), + maxRange: findRange(maxData, 'upper', limit) + }; +} + +function measureText(text, fontSize, context) { + var width = 0; + text = String(text); + // #ifdef MP-ALIPAY || MP-BAIDU || APP-NVUE + context = false; + // #endif + if (context !== false && context !== undefined && context.setFontSize && context.measureText) { + context.setFontSize(fontSize); + return context.measureText(text).width; + } else { + var text = text.split(''); + for (let i = 0; i < text.length; i++) { + let item = text[i]; + if (/[a-zA-Z]/.test(item)) { + width += 7; + } else if (/[0-9]/.test(item)) { + width += 5.5; + } else if (/\./.test(item)) { + width += 2.7; + } else if (/-/.test(item)) { + width += 3.25; + } else if (/:/.test(item)) { + width += 2.5; + } else if (/[\u4e00-\u9fa5]/.test(item)) { + width += 10; + } else if (/\(|\)/.test(item)) { + width += 3.73; + } else if (/\s/.test(item)) { + width += 2.5; + } else if (/%/.test(item)) { + width += 8; + } else { + width += 10; + } + } + return width * fontSize / 10; + } +} + +function dataCombine(series) { + return series.reduce(function(a, b) { + return (a.data ? a.data : a).concat(b.data); + }, []); +} + +function dataCombineStack(series, len) { + var sum = new Array(len); + for (var j = 0; j < sum.length; j++) { + sum[j] = 0; + } + for (var i = 0; i < series.length; i++) { + for (var j = 0; j < sum.length; j++) { + sum[j] += series[i].data[j]; + } + } + return series.reduce(function(a, b) { + return (a.data ? a.data : a).concat(b.data).concat(sum); + }, []); +} + +function getTouches(touches, opts, e) { + let x, y; + if (touches.clientX) { + if (opts.rotate) { + y = opts.height - touches.clientX * opts.pix; + x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix; + } else { + x = touches.clientX * opts.pix; + y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix; + } + } else { + if (opts.rotate) { + y = opts.height - touches.x * opts.pix; + x = touches.y * opts.pix; + } else { + x = touches.x * opts.pix; + y = touches.y * opts.pix; + } + } + return { + x: x, + y: y + } +} + +function getSeriesDataItem(series, index, group) { + var data = []; + var newSeries = []; + var indexIsArr = index.constructor.toString().indexOf('Array') > -1; + if(indexIsArr){ + let tempSeries = filterSeries(series); + for (var i = 0; i < group.length; i++) { + newSeries.push(tempSeries[group[i]]); + } + }else{ + newSeries = series; + }; + for (let i = 0; i < newSeries.length; i++) { + let item = newSeries[i]; + let tmpindex = -1; + if(indexIsArr){ + tmpindex = index[i]; + }else{ + tmpindex = index; + } + if (item.data[tmpindex] !== null && typeof item.data[tmpindex] !== 'undefined' && item.show) { + let seriesItem = {}; + seriesItem.color = item.color; + seriesItem.type = item.type; + seriesItem.style = item.style; + seriesItem.pointShape = item.pointShape; + seriesItem.disableLegend = item.disableLegend; + seriesItem.legendShape = item.legendShape; + seriesItem.name = item.name; + seriesItem.show = item.show; + seriesItem.data = item.formatter ? item.formatter(item.data[tmpindex]) : item.data[tmpindex]; + data.push(seriesItem); + } + } + return data; +} + +function getMaxTextListLength(list, fontSize, context) { + var lengthList = list.map(function(item) { + return measureText(item, fontSize, context); + }); + return Math.max.apply(null, lengthList); +} + +function getRadarCoordinateSeries(length) { + var eachAngle = 2 * Math.PI / length; + var CoordinateSeries = []; + for (var i = 0; i < length; i++) { + CoordinateSeries.push(eachAngle * i); + } + return CoordinateSeries.map(function(item) { + return -1 * item + Math.PI / 2; + }); +} + +function getToolTipData(seriesData, opts, index, group, categories) { + var option = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; + var calPoints = opts.chartData.calPoints?opts.chartData.calPoints:[]; + let points = {}; + if(group.length > 0){ + let filterPoints = []; + for (let i = 0; i < group.length; i++) { + filterPoints.push(calPoints[group[i]]) + } + points = filterPoints[0][index[0]]; + }else{ + for (let i = 0; i < calPoints.length; i++) { + if(calPoints[i][index]){ + points = calPoints[i][index]; + break; + } + } + }; + var textList = seriesData.map(function(item) { + let titleText = null; + if (opts.categories && opts.categories.length>0) { + titleText = categories[index]; + }; + return { + text: option.formatter ? option.formatter(item, titleText, index, opts) : item.name + ': ' + item.data, + color: item.color, + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + }); + var offset = { + x: Math.round(points.x), + y: Math.round(points.y) + }; + return { + textList: textList, + offset: offset + }; +} + +function getMixToolTipData(seriesData, opts, index, categories) { + var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + var points = opts.chartData.xAxisPoints[index] + opts.chartData.eachSpacing / 2; + var textList = seriesData.map(function(item) { + return { + text: option.formatter ? option.formatter(item, categories[index], index, opts) : item.name + ': ' + item.data, + color: item.color, + disableLegend: item.disableLegend ? true : false, + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + }); + textList = textList.filter(function(item) { + if (item.disableLegend !== true) { + return item; + } + }); + var offset = { + x: Math.round(points), + y: 0 + }; + return { + textList: textList, + offset: offset + }; +} + +function getCandleToolTipData(series, seriesData, opts, index, categories, extra) { + var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {}; + var calPoints = opts.chartData.calPoints; + let upColor = extra.color.upFill; + let downColor = extra.color.downFill; + //颜色顺序为开盘,收盘,最低,最高 + let color = [upColor, upColor, downColor, upColor]; + var textList = []; + seriesData.map(function(item) { + if (index == 0) { + if (item.data[1] - item.data[0] < 0) { + color[1] = downColor; + } else { + color[1] = upColor; + } + } else { + if (item.data[0] < series[index - 1][1]) { + color[0] = downColor; + } + if (item.data[1] < item.data[0]) { + color[1] = downColor; + } + if (item.data[2] > series[index - 1][1]) { + color[2] = upColor; + } + if (item.data[3] < series[index - 1][1]) { + color[3] = downColor; + } + } + let text1 = { + text: '开盘:' + item.data[0], + color: color[0], + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + let text2 = { + text: '收盘:' + item.data[1], + color: color[1], + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + let text3 = { + text: '最低:' + item.data[2], + color: color[2], + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + let text4 = { + text: '最高:' + item.data[3], + color: color[3], + legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape + }; + textList.push(text1, text2, text3, text4); + }); + var validCalPoints = []; + var offset = { + x: 0, + y: 0 + }; + for (let i = 0; i < calPoints.length; i++) { + let points = calPoints[i]; + if (typeof points[index] !== 'undefined' && points[index] !== null) { + validCalPoints.push(points[index]); + } + } + offset.x = Math.round(validCalPoints[0][0].x); + return { + textList: textList, + offset: offset + }; +} + +function filterSeries(series) { + let tempSeries = []; + for (let i = 0; i < series.length; i++) { + if (series[i].show == true) { + tempSeries.push(series[i]) + } + } + return tempSeries; +} + +function findCurrentIndex(currentPoints, calPoints, opts, config) { + var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; + var current={ index:-1, group:[] }; + var spacing = opts.chartData.eachSpacing / 2; + let xAxisPoints = []; + if (calPoints && calPoints.length > 0) { + if (!opts.categories) { + spacing = 0; + }else{ + for (let i = 1; i < opts.chartData.xAxisPoints.length; i++) { + xAxisPoints.push(opts.chartData.xAxisPoints[i] - spacing); + } + if ((opts.type == 'line' || opts.type == 'area') && opts.xAxis.boundaryGap == 'justify') { + xAxisPoints = opts.chartData.xAxisPoints; + } + } + if (isInExactChartArea(currentPoints, opts, config)) { + if (!opts.categories) { + let timePoints = Array(calPoints.length); + for (let i = 0; i < calPoints.length; i++) { + timePoints[i] = Array(calPoints[i].length) + for (let j = 0; j < calPoints[i].length; j++) { + timePoints[i][j] = (Math.abs(calPoints[i][j].x - currentPoints.x)); + } + }; + let pointValue = Array(timePoints.length); + let pointIndex = Array(timePoints.length); + for (let i = 0; i < timePoints.length; i++) { + pointValue[i] = Math.min.apply(null, timePoints[i]); + pointIndex[i] = timePoints[i].indexOf(pointValue[i]); + } + let minValue = Math.min.apply(null, pointValue); + current.index = []; + for (let i = 0; i < pointValue.length; i++) { + if(pointValue[i] == minValue){ + current.group.push(i); + current.index.push(pointIndex[i]); + } + }; + }else{ + xAxisPoints.forEach(function(item, index) { + if (currentPoints.x + offset + spacing > item) { + current.index = index; + } + }); + } + } + } + return current; +} + +function findBarChartCurrentIndex(currentPoints, calPoints, opts, config) { + var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; + var current={ index:-1, group:[] }; + var spacing = opts.chartData.eachSpacing / 2; + let yAxisPoints = opts.chartData.yAxisPoints; + if (calPoints && calPoints.length > 0) { + if (isInExactChartArea(currentPoints, opts, config)) { + yAxisPoints.forEach(function(item, index) { + if (currentPoints.y + offset + spacing > item) { + current.index = index; + } + }); + } + } + return current; +} + +function findLegendIndex(currentPoints, legendData, opts) { + let currentIndex = -1; + let gap = 0; + if (isInExactLegendArea(currentPoints, legendData.area)) { + let points = legendData.points; + let index = -1; + for (let i = 0, len = points.length; i < len; i++) { + let item = points[i]; + for (let j = 0; j < item.length; j++) { + index += 1; + let area = item[j]['area']; + if (area && currentPoints.x > area[0] - gap && currentPoints.x < area[2] + gap && currentPoints.y > area[1] - gap && currentPoints.y < area[3] + gap) { + currentIndex = index; + break; + } + } + } + return currentIndex; + } + return currentIndex; +} + +function isInExactLegendArea(currentPoints, area) { + return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y && currentPoints.y < area.end.y; +} + +function isInExactChartArea(currentPoints, opts, config) { + return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] - 10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2]; +} + +function findRadarChartCurrentIndex(currentPoints, radarData, count) { + var eachAngleArea = 2 * Math.PI / count; + var currentIndex = -1; + if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) { + var fixAngle = function fixAngle(angle) { + if (angle < 0) { + angle += 2 * Math.PI; + } + if (angle > 2 * Math.PI) { + angle -= 2 * Math.PI; + } + return angle; + }; + var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x); + angle = -1 * angle; + if (angle < 0) { + angle += 2 * Math.PI; + } + var angleList = radarData.angleList.map(function(item) { + item = fixAngle(-1 * item); + return item; + }); + angleList.forEach(function(item, index) { + var rangeStart = fixAngle(item - eachAngleArea / 2); + var rangeEnd = fixAngle(item + eachAngleArea / 2); + if (rangeEnd < rangeStart) { + rangeEnd += 2 * Math.PI; + } + if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= rangeEnd) { + currentIndex = index; + } + }); + } + return currentIndex; +} + +function findFunnelChartCurrentIndex(currentPoints, funnelData) { + var currentIndex = -1; + for (var i = 0, len = funnelData.series.length; i < len; i++) { + var item = funnelData.series[i]; + if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) { + currentIndex = i; + break; + } + } + return currentIndex; +} + +function findWordChartCurrentIndex(currentPoints, wordData) { + var currentIndex = -1; + for (var i = 0, len = wordData.length; i < len; i++) { + var item = wordData[i]; + if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) { + currentIndex = i; + break; + } + } + return currentIndex; +} + +function findMapChartCurrentIndex(currentPoints, opts) { + var currentIndex = -1; + var cData = opts.chartData.mapData; + var data = opts.series; + var tmp = pointToCoordinate(currentPoints.y, currentPoints.x, cData.bounds, cData.scale, cData.xoffset, cData.yoffset); + var poi = [tmp.x, tmp.y]; + for (var i = 0, len = data.length; i < len; i++) { + var item = data[i].geometry.coordinates; + if (isPoiWithinPoly(poi, item, opts.chartData.mapData.mercator)) { + currentIndex = i; + break; + } + } + return currentIndex; +} + +function findRoseChartCurrentIndex(currentPoints, pieData, opts) { + var currentIndex = -1; + var series = getRoseDataPoints(opts._series_, opts.extra.rose.type, pieData.radius, pieData.radius); + if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) { + var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x); + angle = -angle; + if(opts.extra.rose && opts.extra.rose.offsetAngle){ + angle = angle - opts.extra.rose.offsetAngle * Math.PI / 180; + } + for (var i = 0, len = series.length; i < len; i++) { + if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._rose_proportion_ * 2 * Math.PI)) { + currentIndex = i; + break; + } + } + } + return currentIndex; +} + +function findPieChartCurrentIndex(currentPoints, pieData, opts) { + var currentIndex = -1; + var series = getPieDataPoints(pieData.series); + if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) { + var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x); + angle = -angle; + if(opts.extra.pie && opts.extra.pie.offsetAngle){ + angle = angle - opts.extra.pie.offsetAngle * Math.PI / 180; + } + if(opts.extra.ring && opts.extra.ring.offsetAngle){ + angle = angle - opts.extra.ring.offsetAngle * Math.PI / 180; + } + for (var i = 0, len = series.length; i < len; i++) { + if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._proportion_ * 2 * Math.PI)) { + currentIndex = i; + break; + } + } + } + return currentIndex; +} + +function isInExactPieChartArea(currentPoints, center, radius) { + return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2); +} + + +function splitPoints(points,eachSeries) { + var newPoints = []; + var items = []; + points.forEach(function(item, index) { + if(eachSeries.connectNulls){ + if (item !== null) { + items.push(item); + } + }else{ + if (item !== null) { + items.push(item); + } else { + if (items.length) { + newPoints.push(items); + } + items = []; + } + } + + }); + if (items.length) { + newPoints.push(items); + } + return newPoints; +} + + +function calLegendData(series, opts, config, chartData, context) { + let legendData = { + area: { + start: { + x: 0, + y: 0 + }, + end: { + x: 0, + y: 0 + }, + width: 0, + height: 0, + wholeWidth: 0, + wholeHeight: 0 + }, + points: [], + widthArr: [], + heightArr: [] + }; + if (opts.legend.show === false) { + chartData.legendData = legendData; + return legendData; + } + let padding = opts.legend.padding * opts.pix; + let margin = opts.legend.margin * opts.pix; + let fontSize = opts.legend.fontSize ? opts.legend.fontSize * opts.pix : config.fontSize; + let shapeWidth = 15 * opts.pix; + let shapeRight = 5 * opts.pix; + let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize); + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + let legendList = []; + let widthCount = 0; + let widthCountArr = []; + let currentRow = []; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + const legendText = item.legendText ? item.legendText : item.name; + let itemWidth = shapeWidth + shapeRight + measureText(legendText || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix; + if (widthCount + itemWidth > opts.width - opts.area[1] - opts.area[3]) { + legendList.push(currentRow); + widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix); + widthCount = itemWidth; + currentRow = [item]; + } else { + widthCount += itemWidth; + currentRow.push(item); + } + } + if (currentRow.length) { + legendList.push(currentRow); + widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix); + legendData.widthArr = widthCountArr; + let legendWidth = Math.max.apply(null, widthCountArr); + switch (opts.legend.float) { + case 'left': + legendData.area.start.x = opts.area[3]; + legendData.area.end.x = opts.area[3] + legendWidth + 2 * padding; + break; + case 'right': + legendData.area.start.x = opts.width - opts.area[1] - legendWidth - 2 * padding; + legendData.area.end.x = opts.width - opts.area[1]; + break; + default: + legendData.area.start.x = (opts.width - legendWidth) / 2 - padding; + legendData.area.end.x = (opts.width + legendWidth) / 2 + padding; + } + legendData.area.width = legendWidth + 2 * padding; + legendData.area.wholeWidth = legendWidth + 2 * padding; + legendData.area.height = legendList.length * lineHeight + 2 * padding; + legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin; + legendData.points = legendList; + } + } else { + let len = series.length; + let maxHeight = opts.height - opts.area[0] - opts.area[2] - 2 * margin - 2 * padding; + let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len); + legendData.area.height = maxLength * lineHeight + padding * 2; + legendData.area.wholeHeight = maxLength * lineHeight + padding * 2; + switch (opts.legend.float) { + case 'top': + legendData.area.start.y = opts.area[0] + margin; + legendData.area.end.y = opts.area[0] + margin + legendData.area.height; + break; + case 'bottom': + legendData.area.start.y = opts.height - opts.area[2] - margin - legendData.area.height; + legendData.area.end.y = opts.height - opts.area[2] - margin; + break; + default: + legendData.area.start.y = (opts.height - legendData.area.height) / 2; + legendData.area.end.y = (opts.height + legendData.area.height) / 2; + } + let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1); + let currentRow = []; + for (let i = 0; i < lineNum; i++) { + let temp = series.slice(i * maxLength, i * maxLength + maxLength); + currentRow.push(temp); + } + legendData.points = currentRow; + if (currentRow.length) { + for (let i = 0; i < currentRow.length; i++) { + let item = currentRow[i]; + let maxWidth = 0; + for (let j = 0; j < item.length; j++) { + let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix; + if (itemWidth > maxWidth) { + maxWidth = itemWidth; + } + } + legendData.widthArr.push(maxWidth); + legendData.heightArr.push(item.length * lineHeight + padding * 2); + } + let legendWidth = 0 + for (let i = 0; i < legendData.widthArr.length; i++) { + legendWidth += legendData.widthArr[i]; + } + legendData.area.width = legendWidth - opts.legend.itemGap * opts.pix + 2 * padding; + legendData.area.wholeWidth = legendData.area.width + padding; + } + } + switch (opts.legend.position) { + case 'top': + legendData.area.start.y = opts.area[0] + margin; + legendData.area.end.y = opts.area[0] + margin + legendData.area.height; + break; + case 'bottom': + legendData.area.start.y = opts.height - opts.area[2] - legendData.area.height - margin; + legendData.area.end.y = opts.height - opts.area[2] - margin; + break; + case 'left': + legendData.area.start.x = opts.area[3]; + legendData.area.end.x = opts.area[3] + legendData.area.width; + break; + case 'right': + legendData.area.start.x = opts.width - opts.area[1] - legendData.area.width; + legendData.area.end.x = opts.width - opts.area[1]; + break; + } + chartData.legendData = legendData; + return legendData; +} + +function calCategoriesData(categories, opts, config, eachSpacing, context) { + var result = { + angle: 0, + xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix + }; + var fontSize = opts.xAxis.fontSize * opts.pix; + var categoriesTextLenth = categories.map(function(item,index) { + var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item; + return measureText(String(xitem), fontSize, context); + }); + var maxTextLength = Math.max.apply(this, categoriesTextLenth); + if (opts.xAxis.rotateLabel == true) { + result.angle = opts.xAxis.rotateAngle * Math.PI / 180; + let tempHeight = opts.xAxis.marginTop * opts.pix * 2 + Math.abs(maxTextLength * Math.sin(result.angle)) + tempHeight = tempHeight < fontSize + opts.xAxis.marginTop * opts.pix * 2 ? tempHeight + opts.xAxis.marginTop * opts.pix * 2 : tempHeight; + result.xAxisHeight = tempHeight; + } + if (opts.enableScroll && opts.xAxis.scrollShow) { + result.xAxisHeight += 6 * opts.pix; + } + if (opts.xAxis.disabled){ + result.xAxisHeight = 0; + } + return result; +} + +function getXAxisTextList(series, opts, config, stack) { + var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1; + var data; + if (stack == 'stack') { + data = dataCombineStack(series, opts.categories.length); + } else { + data = dataCombine(series); + } + var sorted = []; + // remove null from data + data = data.filter(function(item) { + //return item !== null; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + return item !== null; + } else { + return item.value !== null; + } + } else { + return item !== null; + } + }); + data.map(function(item) { + if (typeof item === 'object') { + if (item.constructor.toString().indexOf('Array') > -1) { + if (opts.type == 'candle') { + item.map(function(subitem) { + sorted.push(subitem); + }) + } else { + sorted.push(item[0]); + } + } else { + sorted.push(item.value); + } + } else { + sorted.push(item); + } + }) + + var minData = 0; + var maxData = 0; + if (sorted.length > 0) { + minData = Math.min.apply(this, sorted); + maxData = Math.max.apply(this, sorted); + } + //为了兼容v1.9.0之前的项目 + if (index > -1) { + if (typeof opts.xAxis.data[index].min === 'number') { + minData = Math.min(opts.xAxis.data[index].min, minData); + } + if (typeof opts.xAxis.data[index].max === 'number') { + maxData = Math.max(opts.xAxis.data[index].max, maxData); + } + } else { + if (typeof opts.xAxis.min === 'number') { + minData = Math.min(opts.xAxis.min, minData); + } + if (typeof opts.xAxis.max === 'number') { + maxData = Math.max(opts.xAxis.max, maxData); + } + } + if (minData === maxData) { + var rangeSpan = maxData || 10; + maxData += rangeSpan; + } + //var dataRange = getDataRange(minData, maxData); + var minRange = minData; + var maxRange = maxData; + var range = []; + var eachRange = (maxRange - minRange) / opts.xAxis.splitNumber; + for (var i = 0; i <= opts.xAxis.splitNumber; i++) { + range.push(minRange + eachRange * i); + } + return range; +} + +function calXAxisData(series, opts, config, context) { + //堆叠图重算Y轴 + var columnstyle = assign({}, { + type: "" + }, opts.extra.bar); + var result = { + angle: 0, + xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix + }; + result.ranges = getXAxisTextList(series, opts, config, columnstyle.type); + result.rangesFormat = result.ranges.map(function(item) { + //item = opts.xAxis.formatter ? opts.xAxis.formatter(item) : util.toFixed(item, 2); + item = util.toFixed(item, 2); + return item; + }); + var xAxisScaleValues = result.ranges.map(function(item) { + // 如果刻度值是浮点数,则保留两位小数 + item = util.toFixed(item, 2); + // 若有自定义格式则调用自定义的格式化函数 + //item = opts.xAxis.formatter ? opts.xAxis.formatter(Number(item)) : item; + return item; + }); + result = Object.assign(result, getXAxisPoints(xAxisScaleValues, opts, config)); + // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长 + var eachSpacing = result.eachSpacing; + var textLength = xAxisScaleValues.map(function(item) { + return measureText(item, opts.xAxis.fontSize * opts.pix, context); + }); + if (opts.xAxis.disabled === true) { + result.xAxisHeight = 0; + } + return result; +} + +function getRadarDataPoints(angleList, center, radius, series, opts) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + var radarOption = opts.extra.radar || {}; + radarOption.max = radarOption.max || 0; + var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series))); + var data = []; + for (let i = 0; i < series.length; i++) { + let each = series[i]; + let listItem = {}; + listItem.color = each.color; + listItem.legendShape = each.legendShape; + listItem.pointShape = each.pointShape; + listItem.data = []; + each.data.forEach(function(item, index) { + let tmp = {}; + tmp.angle = angleList[index]; + tmp.proportion = item / maxData; + tmp.value = item; + tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * process * Math.sin(tmp.angle), center); + listItem.data.push(tmp); + }); + data.push(listItem); + } + return data; +} + +function getPieDataPoints(series, radius) { + var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + var count = 0; + var _start_ = 0; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + count += item.data; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (count === 0) { + item._proportion_ = 1 / series.length * process; + } else { + item._proportion_ = item.data / count * process; + } + item._radius_ = radius; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item._start_ = _start_; + _start_ += 2 * item._proportion_ * Math.PI; + } + return series; +} + +function getFunnelDataPoints(series, radius, option, eachSpacing) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + for (let i = 0; i < series.length; i++) { + if(option.type == 'funnel'){ + series[i].radius = series[i].data / series[0].data * radius * process; + }else{ + series[i].radius = (eachSpacing * (series.length - i)) / (eachSpacing * series.length) * radius * process; + } + series[i]._proportion_ = series[i].data / series[0].data; + } + // if(option.type !== 'pyramid'){ + // series.reverse(); + // } + return series; +} + +function getRoseDataPoints(series, type, minRadius, radius) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var count = 0; + var _start_ = 0; + var dataArr = []; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + count += item.data; + dataArr.push(item.data); + } + var minData = Math.min.apply(null, dataArr); + var maxData = Math.max.apply(null, dataArr); + var radiusLength = radius - minRadius; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (count === 0) { + item._proportion_ = 1 / series.length * process; + item._rose_proportion_ = 1 / series.length * process; + } else { + item._proportion_ = item.data / count * process; + if(type == 'area'){ + item._rose_proportion_ = 1 / series.length * process; + }else{ + item._rose_proportion_ = item.data / count * process; + } + } + item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData)) || radius; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item._start_ = _start_; + _start_ += 2 * item._rose_proportion_ * Math.PI; + } + return series; +} + +function getArcbarDataPoints(series, arcbarOption) { + var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + if (process == 1) { + process = 0.999999; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + let totalAngle; + if (arcbarOption.type == 'circle') { + totalAngle = 2; + } else { + if(arcbarOption.direction == 'ccw'){ + if (arcbarOption.startAngle < arcbarOption.endAngle) { + totalAngle = 2 + arcbarOption.startAngle - arcbarOption.endAngle; + } else { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + } + }else{ + if (arcbarOption.endAngle < arcbarOption.startAngle) { + totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle; + } else { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + } + } + } + item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle; + if(arcbarOption.direction == 'ccw'){ + item._proportion_ = arcbarOption.startAngle - totalAngle * item.data * process ; + } + if (item._proportion_ >= 2) { + item._proportion_ = item._proportion_ % 2; + } + } + return series; +} + +function getGaugeArcbarDataPoints(series, arcbarOption) { + var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + if (process == 1) { + process = 0.999999; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + let totalAngle; + if (arcbarOption.type == 'circle') { + totalAngle = 2; + } else { + if (arcbarOption.endAngle < arcbarOption.startAngle) { + totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle; + } else { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + } + } + item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle; + if (item._proportion_ >= 2) { + item._proportion_ = item._proportion_ % 2; + } + } + return series; +} + +function getGaugeAxisPoints(categories, startAngle, endAngle) { + let totalAngle; + if (endAngle < startAngle) { + totalAngle = 2 + endAngle - startAngle; + } else { + totalAngle = startAngle - endAngle; + } + let tempStartAngle = startAngle; + for (let i = 0; i < categories.length; i++) { + categories[i].value = categories[i].value === null ? 0 : categories[i].value; + categories[i]._startAngle_ = tempStartAngle; + categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle; + if (categories[i]._endAngle_ >= 2) { + categories[i]._endAngle_ = categories[i]._endAngle_ % 2; + } + tempStartAngle = categories[i]._endAngle_; + } + return categories; +} + +function getGaugeDataPoints(series, categories, gaugeOption) { + let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (gaugeOption.pointer.color == 'auto') { + for (let i = 0; i < categories.length; i++) { + if (item.data <= categories[i].value) { + item.color = categories[i].color; + break; + } + } + } else { + item.color = gaugeOption.pointer.color; + } + let totalAngle; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } + item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle; + item._oldAngle_ = gaugeOption.oldAngle; + if (gaugeOption.oldAngle < gaugeOption.endAngle) { + item._oldAngle_ += 2; + } + if (item.data >= gaugeOption.oldData) { + item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle; + } else { + item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process; + } + if (item._proportion_ >= 2) { + item._proportion_ = item._proportion_ % 2; + } + } + return series; +} + +function getPieTextMaxLength(series, config, context, opts) { + series = getPieDataPoints(series); + let maxLength = 0; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + let text = item.formatter ? item.formatter(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%'; + maxLength = Math.max(maxLength, measureText(text, item.textSize * opts.pix || config.fontSize, context)); + } + return maxLength; +} + +function fixColumeData(points, eachSpacing, columnLen, index, config, opts) { + return points.map(function(item) { + if (item === null) { + return null; + } + var seriesGap = 0; + var categoryGap = 0; + if (opts.type == 'mix') { + seriesGap = opts.extra.mix.column.seriesGap * opts.pix || 0; + categoryGap = opts.extra.mix.column.categoryGap * opts.pix || 0; + } else { + seriesGap = opts.extra.column.seriesGap * opts.pix || 0; + categoryGap = opts.extra.column.categoryGap * opts.pix || 0; + } + seriesGap = Math.min(seriesGap, eachSpacing / columnLen) + categoryGap = Math.min(categoryGap, eachSpacing / columnLen) + item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen); + if (opts.extra.mix && opts.extra.mix.column.width && +opts.extra.mix.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.mix.column.width * opts.pix); + } + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width * opts.pix); + } + if (item.width <= 0) { + item.width = 1; + } + item.x += (index + 0.5 - columnLen / 2) * (item.width + seriesGap); + return item; + }); +} + +function fixBarData(points, eachSpacing, columnLen, index, config, opts) { + return points.map(function(item) { + if (item === null) { + return null; + } + var seriesGap = 0; + var categoryGap = 0; + seriesGap = opts.extra.bar.seriesGap * opts.pix || 0; + categoryGap = opts.extra.bar.categoryGap * opts.pix || 0; + seriesGap = Math.min(seriesGap, eachSpacing / columnLen) + categoryGap = Math.min(categoryGap, eachSpacing / columnLen) + item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen); + if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) { + item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix); + } + if (item.width <= 0) { + item.width = 1; + } + item.y += (index + 0.5 - columnLen / 2) * (item.width + seriesGap); + return item; + }); +} + +function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) { + var categoryGap = opts.extra.column.categoryGap * opts.pix || 0; + return points.map(function(item) { + if (item === null) { + return null; + } + item.width = eachSpacing - 2 * categoryGap; + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width * opts.pix); + } + if (index > 0) { + item.width -= border; + } + return item; + }); +} + +function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) { + var categoryGap = opts.extra.column.categoryGap * opts.pix || 0; + return points.map(function(item, indexn) { + if (item === null) { + return null; + } + item.width = Math.ceil(eachSpacing - 2 * categoryGap); + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width * opts.pix); + } + if (item.width <= 0) { + item.width = 1; + } + return item; + }); +} + +function fixBarStackData(points, eachSpacing, columnLen, index, config, opts, series) { + var categoryGap = opts.extra.bar.categoryGap * opts.pix || 0; + return points.map(function(item, indexn) { + if (item === null) { + return null; + } + item.width = Math.ceil(eachSpacing - 2 * categoryGap); + if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) { + item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix); + } + if (item.width <= 0) { + item.width = 1; + } + return item; + }); +} + +function getXAxisPoints(categories, opts, config) { + var spacingValid = opts.width - opts.area[1] - opts.area[3]; + var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length; + if ((opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' || opts.type == 'bar') && dataCount > 1 && opts.xAxis.boundaryGap == 'justify') { + dataCount -= 1; + } + var widthRatio = 0; + if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){ + if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2 + widthRatio = opts.extra.mount.widthRatio - 1; + dataCount += widthRatio; + } + var eachSpacing = spacingValid / dataCount; + var xAxisPoints = []; + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + categories.forEach(function(item, index) { + xAxisPoints.push(startX + widthRatio / 2 * eachSpacing + index * eachSpacing); + }); + if (opts.xAxis.boundaryGap !== 'justify') { + if (opts.enableScroll === true) { + xAxisPoints.push(startX + widthRatio * eachSpacing + categories.length * eachSpacing); + } else { + xAxisPoints.push(endX); + } + } + return { + xAxisPoints: xAxisPoints, + startX: startX, + endX: endX, + eachSpacing: eachSpacing + }; +} + +function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) { + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var cPoints = []; + item.forEach(function(items, indexs) { + var point = {}; + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2); + var value = items.value || items; + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - Math.round(height) - opts.area[2]; + cPoints.push(point); + }); + points.push(cPoints); + } + }); + return points; +} + +function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) { + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; + var boundaryGap = 'center'; + if (opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' ) { + boundaryGap = opts.xAxis.boundaryGap; + } + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + let xranges, xminRange, xmaxRange; + xranges = [].concat(opts.chartData.xAxisData.ranges); + xminRange = xranges.shift(); + xmaxRange = xranges.pop(); + value = item[1]; + point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange); + if(opts.type == 'bubble'){ + point.r = item[2]; + point.t = item[3]; + } + } else { + value = item.value; + } + } + if (boundaryGap == 'center') { + point.x += eachSpacing / 2; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - height - opts.area[2]; + points.push(point); + } + }); + return points; +} + +function getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process){ + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; + var boundaryGap = opts.xAxis.boundaryGap; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + if(lineOption.animation == 'vertical'){ + point.x = xAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + let xranges, xminRange, xmaxRange; + xranges = [].concat(opts.chartData.xAxisData.ranges); + xminRange = xranges.shift(); + xmaxRange = xranges.pop(); + value = item[1]; + point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange); + } else { + value = item.value; + } + } + if (boundaryGap == 'center') { + point.x += eachSpacing / 2; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - height - opts.area[2]; + points.push(point); + }else{ + point.x = xAxisPoints[0] + eachSpacing * index * process; + var value = item; + if (boundaryGap == 'center') { + point.x += eachSpacing / 2; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + point.y = opts.height - height - opts.area[2]; + points.push(point); + } + } + }); + return points; +} + +function getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process){ + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + let xranges, xminRange, xmaxRange; + xranges = [].concat(opts.chartData.xAxisData.ranges); + xminRange = xranges.shift(); + xmaxRange = xranges.pop(); + value = item[1]; + point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange); + } else { + value = item.value; + } + } + point.x += eachSpacing / 2; + var height = validHeight * (value * process - minRange) / (maxRange - minRange); + point.y = opts.height - height - opts.area[2]; + points.push(point); + } + }); + return points; +} + +function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints) { + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + var mountWidth = eachSpacing * mountOption.widthRatio; + series.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index]; + point.x += eachSpacing / 2; + var value = item.data; + var height = validHeight * (value * process - minRange) / (maxRange - minRange); + point.y = opts.height - height - opts.area[2]; + point.value = value; + point.width = mountWidth; + points.push(point); + } + }); + return points; +} + +function getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config) { + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.y = yAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value; + } + var height = validWidth * (value - minRange) / (maxRange - minRange); + height *= process; + point.height = height; + point.value = value; + point.x = height + opts.area[3]; + points.push(point); + } + }); + return points; +} + +function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) { + var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2); + + if (seriesIndex > 0) { + var value = 0; + for (let i = 0; i <= seriesIndex; i++) { + value += stackSeries[i].data[index]; + } + var value0 = value - item; + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = validHeight * (value0 - minRange) / (maxRange - minRange); + } else { + var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = 0; + } + var heightc = height0; + height *= process; + heightc *= process; + point.y = opts.height - Math.round(height) - opts.area[2]; + point.y0 = opts.height - Math.round(heightc) - opts.area[2]; + points.push(point); + } + }); + return points; +} + +function getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) { + var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1; + var points = []; + var validHeight = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.y = yAxisPoints[index]; + if (seriesIndex > 0) { + var value = 0; + for (let i = 0; i <= seriesIndex; i++) { + value += stackSeries[i].data[index]; + } + var value0 = value - item; + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = validHeight * (value0 - minRange) / (maxRange - minRange); + } else { + var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = 0; + } + var heightc = height0; + height *= process; + heightc *= process; + point.height = height - heightc; + point.x = opts.area[3] + height; + point.x0 = opts.area[3] + heightc; + points.push(point); + } + }); + return points; +} + +function getYAxisTextList(series, opts, config, stack, yData) { + var index = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : -1; + var data; + if (stack == 'stack') { + data = dataCombineStack(series, opts.categories.length); + } else { + data = dataCombine(series); + } + var sorted = []; + // remove null from data + data = data.filter(function(item) { + //return item !== null; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + return item !== null; + } else { + return item.value !== null; + } + } else { + return item !== null; + } + }); + data.map(function(item) { + if (typeof item === 'object') { + if (item.constructor.toString().indexOf('Array') > -1) { + if (opts.type == 'candle') { + item.map(function(subitem) { + sorted.push(subitem); + }) + } else { + sorted.push(item[1]); + } + } else { + sorted.push(item.value); + } + } else { + sorted.push(item); + } + }) + var minData = yData.min || 0; + var maxData = yData.max || 0; + if (sorted.length > 0) { + minData = Math.min.apply(this, sorted); + maxData = Math.max.apply(this, sorted); + } + if (minData === maxData) { + if(maxData == 0){ + maxData = 10; + }else{ + minData = 0; + } + } + var dataRange = getDataRange(minData, maxData); + var minRange = (yData.min === undefined || yData.min === null) ? dataRange.minRange : yData.min; + var maxRange = (yData.max === undefined || yData.max === null) ? dataRange.maxRange : yData.max; + var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber; + var range = []; + for (var i = 0; i <= opts.yAxis.splitNumber; i++) { + range.push(minRange + eachRange * i); + } + return range.reverse(); +} + +function calYAxisData(series, opts, config, context) { + //堆叠图重算Y轴 + var columnstyle = assign({}, { + type: "" + }, opts.extra.column); + //如果是多Y轴,重新计算 + var YLength = opts.yAxis.data.length; + var newSeries = new Array(YLength); + if (YLength > 0) { + for (let i = 0; i < YLength; i++) { + newSeries[i] = []; + for (let j = 0; j < series.length; j++) { + if (series[j].index == i) { + newSeries[i].push(series[j]); + } + } + } + var rangesArr = new Array(YLength); + var rangesFormatArr = new Array(YLength); + var yAxisWidthArr = new Array(YLength); + + for (let i = 0; i < YLength; i++) { + let yData = opts.yAxis.data[i]; + //如果总开关不显示,强制每个Y轴为不显示 + if (opts.yAxis.disabled == true) { + yData.disabled = true; + } + if(yData.type === 'categories'){ + if(!yData.formatter){ + yData.formatter = (val,index,opts) => {return val + (yData.unit || '')}; + } + yData.categories = yData.categories || opts.categories; + rangesArr[i] = yData.categories; + }else{ + if(!yData.formatter){ + yData.formatter = (val,index,opts) => {return util.toFixed(val, yData.tofix || 0) + (yData.unit || '')}; + } + rangesArr[i] = getYAxisTextList(newSeries[i], opts, config, columnstyle.type, yData, i); + } + let yAxisFontSizes = yData.fontSize * opts.pix || config.fontSize; + yAxisWidthArr[i] = { + position: yData.position ? yData.position : 'left', + width: 0 + }; + rangesFormatArr[i] = rangesArr[i].map(function(items,index) { + items = yData.formatter(items,index,opts); + yAxisWidthArr[i].width = Math.max(yAxisWidthArr[i].width, measureText(items, yAxisFontSizes, context) + 5); + return items; + }); + let calibration = yData.calibration ? 4 * opts.pix : 0; + yAxisWidthArr[i].width += calibration + 3 * opts.pix; + if (yData.disabled === true) { + yAxisWidthArr[i].width = 0; + } + } + } else { + var rangesArr = new Array(1); + var rangesFormatArr = new Array(1); + var yAxisWidthArr = new Array(1); + if(opts.type === 'bar'){ + rangesArr[0] = opts.categories; + if(!opts.yAxis.formatter){ + opts.yAxis.formatter = (val,index,opts) => {return val + (opts.yAxis.unit || '')} + } + }else{ + if(!opts.yAxis.formatter){ + opts.yAxis.formatter = (val,index,opts) => {return val.toFixed(opts.yAxis.tofix ) + (opts.yAxis.unit || '')} + } + rangesArr[0] = getYAxisTextList(series, opts, config, columnstyle.type, {}); + } + yAxisWidthArr[0] = { + position: 'left', + width: 0 + }; + var yAxisFontSize = opts.yAxis.fontSize * opts.pix || config.fontSize; + rangesFormatArr[0] = rangesArr[0].map(function(item,index) { + item = opts.yAxis.formatter(item,index,opts); + yAxisWidthArr[0].width = Math.max(yAxisWidthArr[0].width, measureText(item, yAxisFontSize, context) + 5); + return item; + }); + yAxisWidthArr[0].width += 3 * opts.pix; + if (opts.yAxis.disabled === true) { + yAxisWidthArr[0] = { + position: 'left', + width: 0 + }; + opts.yAxis.data[0] = { + disabled: true + }; + } else { + opts.yAxis.data[0] = { + disabled: false, + position: 'left', + max: opts.yAxis.max, + min: opts.yAxis.min, + formatter: opts.yAxis.formatter + }; + if(opts.type === 'bar'){ + opts.yAxis.data[0].categories = opts.categories; + opts.yAxis.data[0].type = 'categories'; + } + } + } + return { + rangesFormat: rangesFormatArr, + ranges: rangesArr, + yAxisWidth: yAxisWidthArr + }; +} + +function calTooltipYAxisData(point, series, opts, config, eachSpacing) { + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let minAxis = opts.area[0]; + let items = []; + for (let i = 0; i < ranges.length; i++) { + let maxVal = Math.max.apply(this, ranges[i]); + let minVal = Math.min.apply(this, ranges[i]); + let item = maxVal - (maxVal - minVal) * (point - minAxis) / spacingValid; + item = opts.yAxis.data && opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item, i, opts) : item.toFixed(0); + items.push(String(item)) + } + return items; +} + +function calMarkLineData(points, opts) { + let minRange, maxRange; + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + for (let i = 0; i < points.length; i++) { + points[i].yAxisIndex = points[i].yAxisIndex ? points[i].yAxisIndex : 0; + let range = [].concat(opts.chartData.yAxisData.ranges[points[i].yAxisIndex]); + minRange = range.pop(); + maxRange = range.shift(); + let height = spacingValid * (points[i].value - minRange) / (maxRange - minRange); + points[i].y = opts.height - Math.round(height) - opts.area[2]; + } + return points; +} + +function contextRotate(context, opts) { + if (opts.rotateLock !== true) { + context.translate(opts.height, 0); + context.rotate(90 * Math.PI / 180); + } else if (opts._rotate_ !== true) { + context.translate(opts.height, 0); + context.rotate(90 * Math.PI / 180); + opts._rotate_ = true; + } +} + +function drawPointShape(points, color, shape, context, opts) { + context.beginPath(); + if (opts.dataPointShapeType == 'hollow') { + context.setStrokeStyle(color); + context.setFillStyle(opts.background); + context.setLineWidth(2 * opts.pix); + } else { + context.setStrokeStyle("#ffffff"); + context.setFillStyle(color); + context.setLineWidth(1 * opts.pix); + } + if (shape === 'diamond') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y); + context.lineTo(item.x, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'circle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x + 2.5 * opts.pix, item.y); + context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false); + } + }); + } else if (shape === 'square') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x - 3.5, item.y - 3.5); + context.rect(item.x - 3.5, item.y - 3.5, 7, 7); + } + }); + } else if (shape === 'triangle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y + 4.5); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'none') { + return; + } + context.closePath(); + context.fill(); + context.stroke(); +} + +function drawActivePoint(points, color, shape, context, opts, option, seriesIndex) { + if(!opts.tooltip){ + return + } + if(opts.tooltip.group.length>0 && opts.tooltip.group.includes(seriesIndex) == false){ + return + } + var pointIndex = typeof opts.tooltip.index === 'number' ? opts.tooltip.index : opts.tooltip.index[opts.tooltip.group.indexOf(seriesIndex)]; + context.beginPath(); + if (option.activeType == 'hollow') { + context.setStrokeStyle(color); + context.setFillStyle(opts.background); + context.setLineWidth(2 * opts.pix); + } else { + context.setStrokeStyle("#ffffff"); + context.setFillStyle(color); + context.setLineWidth(1 * opts.pix); + } + if (shape === 'diamond') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index ) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y); + context.lineTo(item.x, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'circle') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x + 2.5 * opts.pix, item.y); + context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false); + } + }); + } else if (shape === 'square') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x - 3.5, item.y - 3.5); + context.rect(item.x - 3.5, item.y - 3.5, 7, 7); + } + }); + } else if (shape === 'triangle') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y + 4.5); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'none') { + return; + } + context.closePath(); + context.fill(); + context.stroke(); +} + +function drawRingTitle(opts, config, context, center) { + var titlefontSize = opts.title.fontSize || config.titleFontSize; + var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize; + var title = opts.title.name || ''; + var subtitle = opts.subtitle.name || ''; + var titleFontColor = opts.title.color || opts.fontColor; + var subtitleFontColor = opts.subtitle.color || opts.fontColor; + var titleHeight = title ? titlefontSize : 0; + var subtitleHeight = subtitle ? subtitlefontSize : 0; + var margin = 5; + if (subtitle) { + var textWidth = measureText(subtitle, subtitlefontSize * opts.pix, context); + var startX = center.x - textWidth / 2 + (opts.subtitle.offsetX|| 0) * opts.pix ; + var startY = center.y + subtitlefontSize * opts.pix / 2 + (opts.subtitle.offsetY || 0) * opts.pix; + if (title) { + startY += (titleHeight * opts.pix + margin) / 2; + } + context.beginPath(); + context.setFontSize(subtitlefontSize * opts.pix); + context.setFillStyle(subtitleFontColor); + context.fillText(subtitle, startX, startY); + context.closePath(); + context.stroke(); + } + if (title) { + var _textWidth = measureText(title, titlefontSize * opts.pix, context); + var _startX = center.x - _textWidth / 2 + (opts.title.offsetX || 0); + var _startY = center.y + titlefontSize * opts.pix / 2 + (opts.title.offsetY || 0) * opts.pix; + if (subtitle) { + _startY -= (subtitleHeight * opts.pix + margin) / 2; + } + context.beginPath(); + context.setFontSize(titlefontSize * opts.pix); + context.setFillStyle(titleFontColor); + context.fillText(title, _startX, _startY); + context.closePath(); + context.stroke(); + } +} + +function drawPointText(points, series, config, context, opts) { + // 绘制数据文案 + var data = series.data; + var textOffset = series.textOffset ? series.textOffset : 0; + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + var fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(series.textColor || opts.fontColor); + var value = data[index] + if (typeof data[index] === 'object' && data[index] !== null) { + if (data[index].constructor.toString().indexOf('Array')>-1) { + value = data[index][1]; + } else { + value = data[index].value + } + } + var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value; + context.setTextAlign('center'); + context.fillText(String(formatVal), item.x, item.y - 4 + textOffset * opts.pix); + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + } + }); +} + +function drawColumePointText(points, series, config, context, opts) { + // 绘制数据文案 + var data = series.data; + var textOffset = series.textOffset ? series.textOffset : 0; + var Position = opts.extra.column.labelPosition; + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + var fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(series.textColor || opts.fontColor); + var value = data[index] + if (typeof data[index] === 'object' && data[index] !== null) { + if (data[index].constructor.toString().indexOf('Array')>-1) { + value = data[index][1]; + } else { + value = data[index].value + } + } + var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value; + context.setTextAlign('center'); + var startY = item.y - 4 * opts.pix + textOffset * opts.pix; + if(item.y > series.zeroPoints){ + startY = item.y + textOffset * opts.pix + fontSize; + } + if(Position == 'insideTop'){ + startY = item.y + fontSize + textOffset * opts.pix; + if(item.y > series.zeroPoints){ + startY = item.y - textOffset * opts.pix - 4 * opts.pix; + } + } + if(Position == 'center'){ + startY = item.y + textOffset * opts.pix + (opts.height - opts.area[2] - item.y + fontSize)/2; + if(series.zeroPoints < opts.height - opts.area[2]){ + startY = item.y + textOffset * opts.pix + (series.zeroPoints - item.y + fontSize)/2; + } + if(item.y > series.zeroPoints){ + startY = item.y - textOffset * opts.pix - (item.y - series.zeroPoints - fontSize)/2; + } + if(opts.extra.column.type == 'stack'){ + startY = item.y + textOffset * opts.pix + (item.y0 - item.y + fontSize)/2; + } + } + if(Position == 'bottom'){ + startY = opts.height - opts.area[2] + textOffset * opts.pix - 4 * opts.pix; + if(series.zeroPoints < opts.height - opts.area[2]){ + startY = series.zeroPoints + textOffset * opts.pix - 4 * opts.pix; + } + if(item.y > series.zeroPoints){ + startY = series.zeroPoints - textOffset * opts.pix + fontSize + 2 * opts.pix; + } + if(opts.extra.column.type == 'stack'){ + startY = item.y0 + textOffset * opts.pix - 4 * opts.pix; + } + } + context.fillText(String(formatVal), item.x, startY); + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + } + }); +} + +function drawMountPointText(points, series, config, context, opts, zeroPoints) { + // 绘制数据文案 + var data = series.data; + var textOffset = series.textOffset ? series.textOffset : 0; + var Position = opts.extra.mount.labelPosition; + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + var fontSize = series[index].textSize ? series[index].textSize * opts.pix : config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(series[index].textColor || opts.fontColor); + var value = item.value + var formatVal = series[index].formatter ? series[index].formatter(value,index,series,opts) : value; + context.setTextAlign('center'); + var startY = item.y - 4 * opts.pix + textOffset * opts.pix; + if(item.y > zeroPoints){ + startY = item.y + textOffset * opts.pix + fontSize; + } + context.fillText(String(formatVal), item.x, startY); + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + } + }); +} + +function drawBarPointText(points, series, config, context, opts) { + // 绘制数据文案 + var data = series.data; + var textOffset = series.textOffset ? series.textOffset : 0; + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + var fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(series.textColor || opts.fontColor); + var value = data[index] + if (typeof data[index] === 'object' && data[index] !== null) { + value = data[index].value ; + } + var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value; + context.setTextAlign('left'); + context.fillText(String(formatVal), item.x + 4 * opts.pix , item.y + fontSize / 2 - 3 ); + context.closePath(); + context.stroke(); + } + }); +} + +function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) { + radius -= gaugeOption.width / 2 + gaugeOption.labelOffset * opts.pix; + radius = radius < 10 ? 10 : radius; + let totalAngle; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } + let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; + let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber; + let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber; + let nowAngle = gaugeOption.startAngle; + let nowNumber = gaugeOption.startNumber; + for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) { + var pos = { + x: radius * Math.cos(nowAngle * Math.PI), + y: radius * Math.sin(nowAngle * Math.PI) + }; + var labelText = gaugeOption.formatter ? gaugeOption.formatter(nowNumber,i,opts) : nowNumber; + pos.x += centerPosition.x - measureText(labelText, config.fontSize, context) / 2; + pos.y += centerPosition.y; + var startX = pos.x; + var startY = pos.y; + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(gaugeOption.labelColor || opts.fontColor); + context.fillText(labelText, startX, startY + config.fontSize / 2); + context.closePath(); + context.stroke(); + nowAngle += splitAngle; + if (nowAngle >= 2) { + nowAngle = nowAngle % 2; + } + nowNumber += splitNumber; + } +} + +function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) { + var radarOption = opts.extra.radar || {}; + angleList.forEach(function(angle, index) { + if(radarOption.labelPointShow === true && opts.categories[index] !== ''){ + var posPoint = { + x: radius * Math.cos(angle), + y: radius * Math.sin(angle) + }; + var posPointAxis = convertCoordinateOrigin(posPoint.x, posPoint.y, centerPosition); + context.setFillStyle(radarOption.labelPointColor); + context.beginPath(); + context.arc(posPointAxis.x, posPointAxis.y, radarOption.labelPointRadius * opts.pix, 0, 2 * Math.PI, false); + context.closePath(); + context.fill(); + } + if(radarOption.labelShow === true){ + var pos = { + x: (radius + config.radarLabelTextMargin * opts.pix) * Math.cos(angle), + y: (radius + config.radarLabelTextMargin * opts.pix) * Math.sin(angle) + }; + var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition); + var startX = posRelativeCanvas.x; + var startY = posRelativeCanvas.y; + if (util.approximatelyEqual(pos.x, 0)) { + startX -= measureText(opts.categories[index] || '', config.fontSize, context) / 2; + } else if (pos.x < 0) { + startX -= measureText(opts.categories[index] || '', config.fontSize, context); + } + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(radarOption.labelColor || opts.fontColor); + context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2); + context.closePath(); + context.stroke(); + } + }); + +} + +function drawPieText(series, opts, config, context, radius, center) { + var lineRadius = config.pieChartLinePadding; + var textObjectCollection = []; + var lastTextObject = null; + var seriesConvert = series.map(function(item,index) { + var text = item.formatter ? item.formatter(item,index,series,opts) : util.toFixed(item._proportion_.toFixed(4) * 100) + '%'; + text = item.labelText ? item.labelText : text; + var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2); + if (item._rose_proportion_) { + arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._rose_proportion_ / 2); + } + var color = item.color; + var radius = item._radius_; + return { + arc: arc, + text: text, + color: color, + radius: radius, + textColor: item.textColor, + textSize: item.textSize, + labelShow: item.labelShow + }; + }); + for (let i = 0; i < seriesConvert.length; i++) { + let item = seriesConvert[i]; + // line end + let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius); + let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius); + // line start + let orginX2 = Math.cos(item.arc) * item.radius; + let orginY2 = Math.sin(item.arc) * item.radius; + // text start + let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding; + let orginY3 = orginY1; + let textWidth = measureText(item.text, item.textSize * opts.pix || config.fontSize, context); + let startY = orginY3; + if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, { + x: orginX3 + })) { + if (orginX3 > 0) { + startY = Math.min(orginY3, lastTextObject.start.y); + } else if (orginX1 < 0) { + startY = Math.max(orginY3, lastTextObject.start.y); + } else { + if (orginY3 > 0) { + startY = Math.max(orginY3, lastTextObject.start.y); + } else { + startY = Math.min(orginY3, lastTextObject.start.y); + } + } + } + if (orginX3 < 0) { + orginX3 -= textWidth; + } + let textObject = { + lineStart: { + x: orginX2, + y: orginY2 + }, + lineEnd: { + x: orginX1, + y: orginY1 + }, + start: { + x: orginX3, + y: startY + }, + width: textWidth, + height: config.fontSize, + text: item.text, + color: item.color, + textColor: item.textColor, + textSize: item.textSize + }; + lastTextObject = avoidCollision(textObject, lastTextObject); + textObjectCollection.push(lastTextObject); + } + for (let i = 0; i < textObjectCollection.length; i++) { + if(seriesConvert[i].labelShow === false){ + continue; + } + let item = textObjectCollection[i]; + let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center); + let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center); + let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center); + context.setLineWidth(1 * opts.pix); + context.setFontSize(item.textSize * opts.pix || config.fontSize); + context.beginPath(); + context.setStrokeStyle(item.color); + context.setFillStyle(item.color); + context.moveTo(lineStartPoistion.x, lineStartPoistion.y); + let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x; + let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5; + context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y); + context.moveTo(lineStartPoistion.x, lineStartPoistion.y); + context.stroke(); + context.closePath(); + context.beginPath(); + context.moveTo(textPosition.x + item.width, textPosition.y); + context.arc(curveStartX, textPosition.y, 2 * opts.pix, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFontSize(item.textSize * opts.pix || config.fontSize); + context.setFillStyle(item.textColor || opts.fontColor); + context.fillText(item.text, textStartX, textPosition.y + 3); + context.closePath(); + context.stroke(); + context.closePath(); + } +} + +function drawToolTipSplitLine(offsetX, opts, config, context) { + var toolTipOption = opts.extra.tooltip || {}; + toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType; + toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength; + var startY = opts.area[0]; + var endY = opts.height - opts.area[2]; + if (toolTipOption.gridType == 'dash') { + context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]); + } + context.setStrokeStyle(toolTipOption.gridColor || '#cccccc'); + context.setLineWidth(1 * opts.pix); + context.beginPath(); + context.moveTo(offsetX, startY); + context.lineTo(offsetX, endY); + context.stroke(); + context.setLineDash([]); + if (toolTipOption.xAxisLabel) { + let labelText = opts.categories[opts.tooltip.index]; + context.setFontSize(config.fontSize); + let textWidth = measureText(labelText, config.fontSize, context); + let textX = offsetX - 0.5 * textWidth; + let textY = endY + 2 * opts.pix; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); + context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); + context.setLineWidth(1 * opts.pix); + context.rect(textX - toolTipOption.boxPadding * opts.pix, textY, textWidth + 2 * toolTipOption.boxPadding * opts.pix, config.fontSize + 2 * toolTipOption.boxPadding * opts.pix); + context.closePath(); + context.stroke(); + context.fill(); + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor); + context.fillText(String(labelText), textX, textY + toolTipOption.boxPadding * opts.pix + config.fontSize); + context.closePath(); + context.stroke(); + } +} + +function drawMarkLine(opts, config, context) { + let markLineOption = assign({}, { + type: 'solid', + dashLength: 4, + data: [] + }, opts.extra.markLine); + let startX = opts.area[3]; + let endX = opts.width - opts.area[1]; + let points = calMarkLineData(markLineOption.data, opts); + for (let i = 0; i < points.length; i++) { + let item = assign({}, { + lineColor: '#DE4A42', + showLabel: false, + labelFontSize: 13, + labelPadding: 6, + labelFontColor: '#666666', + labelBgColor: '#DFE8FF', + labelBgOpacity: 0.8, + labelAlign: 'left', + labelOffsetX: 0, + labelOffsetY: 0, + }, points[i]); + if (markLineOption.type == 'dash') { + context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]); + } + context.setStrokeStyle(item.lineColor); + context.setLineWidth(1 * opts.pix); + context.beginPath(); + context.moveTo(startX, item.y); + context.lineTo(endX, item.y); + context.stroke(); + context.setLineDash([]); + if (item.showLabel) { + let fontSize = item.labelFontSize * opts.pix; + let labelText = item.labelText ? item.labelText : item.value; + context.setFontSize(fontSize); + let textWidth = measureText(labelText, fontSize, context); + let bgWidth = textWidth + item.labelPadding * opts.pix * 2; + let bgStartX = item.labelAlign == 'left' ? opts.area[3] - bgWidth : opts.width - opts.area[1]; + bgStartX += item.labelOffsetX; + let bgStartY = item.y - 0.5 * fontSize - item.labelPadding * opts.pix; + bgStartY += item.labelOffsetY; + let textX = bgStartX + item.labelPadding * opts.pix; + let textY = item.y; + context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity)); + context.setStrokeStyle(item.labelBgColor); + context.setLineWidth(1 * opts.pix); + context.beginPath(); + context.rect(bgStartX, bgStartY, bgWidth, fontSize + 2 * item.labelPadding * opts.pix); + context.closePath(); + context.stroke(); + context.fill(); + context.setFontSize(fontSize); + context.setTextAlign('left'); + context.setFillStyle(item.labelFontColor); + context.fillText(String(labelText), textX, bgStartY + fontSize + item.labelPadding * opts.pix/2); + context.stroke(); + context.setTextAlign('left'); + } + } +} + +function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) { + var toolTipOption = assign({}, { + gridType: 'solid', + dashLength: 4 + }, opts.extra.tooltip); + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + if (toolTipOption.gridType == 'dash') { + context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]); + } + context.setStrokeStyle(toolTipOption.gridColor || '#cccccc'); + context.setLineWidth(1 * opts.pix); + context.beginPath(); + context.moveTo(startX, opts.tooltip.offset.y); + context.lineTo(endX, opts.tooltip.offset.y); + context.stroke(); + context.setLineDash([]); + if (toolTipOption.yAxisLabel) { + let boxPadding = toolTipOption.boxPadding * opts.pix; + let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing); + let widthArr = opts.chartData.yAxisData.yAxisWidth; + let tStartLeft = opts.area[3]; + let tStartRight = opts.width - opts.area[1]; + for (let i = 0; i < labelText.length; i++) { + context.setFontSize(toolTipOption.fontSize * opts.pix); + let textWidth = measureText(labelText[i], toolTipOption.fontSize * opts.pix, context); + let bgStartX, bgEndX, bgWidth; + if (widthArr[i].position == 'left') { + bgStartX = tStartLeft - (textWidth + boxPadding * 2) - 2 * opts.pix; + bgEndX = Math.max(bgStartX, bgStartX + textWidth + boxPadding * 2); + } else { + bgStartX = tStartRight + 2 * opts.pix; + bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + boxPadding * 2); + } + bgWidth = bgEndX - bgStartX; + let textX = bgStartX + (bgWidth - textWidth) / 2; + let textY = opts.tooltip.offset.y; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); + context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); + context.setLineWidth(1 * opts.pix); + context.rect(bgStartX, textY - 0.5 * config.fontSize - boxPadding, bgWidth, config.fontSize + 2 * boxPadding); + context.closePath(); + context.stroke(); + context.fill(); + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor); + context.fillText(labelText[i], textX, textY + 0.5 * config.fontSize); + context.closePath(); + context.stroke(); + if (widthArr[i].position == 'left') { + tStartLeft -= (widthArr[i].width + opts.yAxis.padding * opts.pix); + } else { + tStartRight += widthArr[i].width + opts.yAxis.padding * opts.pix; + } + } + } +} + +function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) { + var toolTipOption = assign({}, { + activeBgColor: '#000000', + activeBgOpacity: 0.08, + activeWidth: eachSpacing + }, opts.extra.column); + toolTipOption.activeWidth = toolTipOption.activeWidth > eachSpacing ? eachSpacing : toolTipOption.activeWidth; + var startY = opts.area[0]; + var endY = opts.height - opts.area[2]; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity)); + context.rect(offsetX - toolTipOption.activeWidth / 2, startY, toolTipOption.activeWidth, endY - startY); + context.closePath(); + context.fill(); + context.setFillStyle("#FFFFFF"); +} + +function drawBarToolTipSplitArea(offsetX, opts, config, context, eachSpacing) { + var toolTipOption = assign({}, { + activeBgColor: '#000000', + activeBgOpacity: 0.08 + }, opts.extra.bar); + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity)); + context.rect( startX ,offsetX - eachSpacing / 2 , endX - startX,eachSpacing); + context.closePath(); + context.fill(); + context.setFillStyle("#FFFFFF"); +} + + +function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) { + var toolTipOption = assign({}, { + showBox: true, + showArrow: true, + showCategory: false, + bgColor: '#000000', + bgOpacity: 0.7, + borderColor: '#000000', + borderWidth: 0, + borderRadius: 0, + borderOpacity: 0.7, + boxPadding: 3, + fontColor: '#FFFFFF', + fontSize: 13, + lineHeight: 20, + legendShow: true, + legendShape: 'auto', + splitLine: true, + }, opts.extra.tooltip); + if(toolTipOption.showCategory==true && opts.categories){ + textList.unshift({text:opts.categories[opts.tooltip.index],color:null}) + } + var fontSize = toolTipOption.fontSize * opts.pix; + var lineHeight = toolTipOption.lineHeight * opts.pix; + var boxPadding = toolTipOption.boxPadding * opts.pix; + var legendWidth = fontSize; + var legendMarginRight = 5 * opts.pix; + if(toolTipOption.legendShow == false){ + legendWidth = 0; + legendMarginRight = 0; + } + var arrowWidth = toolTipOption.showArrow ? 8 * opts.pix : 0; + var isOverRightBorder = false; + if (opts.type == 'line' || opts.type == 'mount' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') { + if (toolTipOption.splitLine == true) { + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context); + } + } + offset = assign({ + x: 0, + y: 0 + }, offset); + offset.y -= 8 * opts.pix; + var textWidth = textList.map(function(item) { + return measureText(item.text, fontSize, context); + }); + var toolTipWidth = legendWidth + legendMarginRight + 4 * boxPadding + Math.max.apply(null, textWidth); + var toolTipHeight = 2 * boxPadding + textList.length * lineHeight; + if (toolTipOption.showBox == false) { + return + } + // if beyond the right border + if (offset.x - Math.abs(opts._scrollDistance_ || 0) + arrowWidth + toolTipWidth > opts.width) { + isOverRightBorder = true; + } + if (toolTipHeight + offset.y > opts.height) { + offset.y = opts.height - toolTipHeight; + } + // draw background rect + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.bgColor, toolTipOption.bgOpacity)); + context.setLineWidth(toolTipOption.borderWidth * opts.pix); + context.setStrokeStyle(hexToRgb(toolTipOption.borderColor, toolTipOption.borderOpacity)); + var radius = toolTipOption.borderRadius; + if (isOverRightBorder) { + // 增加左侧仍然超出的判断 + if(toolTipWidth + arrowWidth > opts.width){ + offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width) + } + if(toolTipWidth > offset.x){ + offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width) + } + if (toolTipOption.showArrow) { + context.moveTo(offset.x, offset.y + 10 * opts.pix); + context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix); + } + context.arc(offset.x - arrowWidth - radius, offset.y + toolTipHeight - radius, radius, 0, Math.PI / 2, false); + context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + toolTipHeight - radius, radius, + Math.PI / 2, Math.PI, false); + context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false); + context.arc(offset.x - arrowWidth - radius, offset.y + radius, radius, -Math.PI / 2, 0, false); + if (toolTipOption.showArrow) { + context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix - 5 * opts.pix); + context.lineTo(offset.x, offset.y + 10 * opts.pix); + } + } else { + if (toolTipOption.showArrow) { + context.moveTo(offset.x, offset.y + 10 * opts.pix); + context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix - 5 * opts.pix); + } + context.arc(offset.x + arrowWidth + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false); + context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + radius, radius, -Math.PI / 2, 0, + false); + context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + toolTipHeight - radius, radius, 0, + Math.PI / 2, false); + context.arc(offset.x + arrowWidth + radius, offset.y + toolTipHeight - radius, radius, Math.PI / 2, Math.PI, false); + if (toolTipOption.showArrow) { + context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix); + context.lineTo(offset.x, offset.y + 10 * opts.pix); + } + } + context.closePath(); + context.fill(); + if (toolTipOption.borderWidth > 0) { + context.stroke(); + } + // draw legend + if(toolTipOption.legendShow){ + textList.forEach(function(item, index) { + if (item.color !== null) { + context.beginPath(); + context.setFillStyle(item.color); + var startX = offset.x + arrowWidth + 2 * boxPadding; + var startY = offset.y + (lineHeight - fontSize) / 2 + lineHeight * index + boxPadding + 1; + if (isOverRightBorder) { + startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding; + } + switch (item.legendShape) { + case 'line': + context.moveTo(startX, startY + 0.5 * legendWidth - 2 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 2 * opts.pix, legendWidth, 4 * opts.pix); + break; + case 'triangle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + break; + case 'diamond': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + break; + case 'circle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth); + context.arc(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth, 5 * opts.pix, 0, 2 * Math.PI); + break; + case 'rect': + context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + break; + case 'square': + context.moveTo(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix); + break; + default: + context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + } + context.closePath(); + context.fill(); + } + }); + } + + // draw text list + textList.forEach(function(item, index) { + var startX = offset.x + arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight; + if (isOverRightBorder) { + startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight; + } + var startY = offset.y + lineHeight * index + (lineHeight - fontSize)/2 - 1 + boxPadding + fontSize; + context.beginPath(); + context.setFontSize(fontSize); + context.setTextBaseline('normal'); + context.setFillStyle(toolTipOption.fontColor); + context.fillText(item.text, startX, startY); + context.closePath(); + context.stroke(); + }); +} + +function drawColumnDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let columnOption = assign({}, { + type: 'group', + width: eachSpacing / 2, + meterBorder: 4, + meterFillColor: '#FFFFFF', + barBorderCircle: false, + barBorderRadius: [], + seriesGap: 2, + linearType: 'none', + linearOpacity: 1, + customColor: [], + colorStop: 0, + labelPosition: 'outside' + }, opts.extra.column); + let calPoints = []; + context.save(); + let leftNum = -2; + let rightNum = xAxisPoints.length + 2; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2; + rightNum = leftNum + opts.xAxis.itemCount + 4; + } + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing); + } + columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config); + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + + // 计算0轴坐标 + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange); + let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2]; + eachSeries.zeroPoints = zeroPoints; + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process); + var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + calPoints.push(tooltipPoints); + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + //fix issues/I27B1N yyoinge & Joeshu + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || eachSeries.color + var strokeColor = item.color || eachSeries.color + if (columnOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (columnOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity)); + grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + // 圆角边框 + if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { + const left = startX; + const top = item.y > zeroPoints ? zeroPoints : item.y; + const width = item.width; + const height = Math.abs(zeroPoints - item.y); + if (columnOption.barBorderCircle) { + columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; + } + if(item.y > zeroPoints){ + columnOption.barBorderRadius = [0, 0,width / 2, width / 2]; + } + let [r0, r1, r2, r3] = columnOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + } else { + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); + context.lineTo(startX, item.y); + context.setLineWidth(1) + context.setStrokeStyle(strokeColor); + } + context.setFillStyle(fillColor); + context.closePath(); + //context.stroke(); + context.fill(); + } + }; + break; + case 'stack': + // 绘制堆叠数据图 + var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + calPoints.push(points); + points = fixColumeStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + context.beginPath(); + var fillColor = item.color || eachSeries.color; + var startX = item.x - item.width / 2 + 1; + var height = opts.height - item.y - opts.area[2]; + var height0 = opts.height - item.y0 - opts.area[2]; + if (seriesIndex > 0) { + height -= height0; + } + context.setFillStyle(fillColor); + context.moveTo(startX, item.y); + context.fillRect(startX, item.y, item.width, height); + context.closePath(); + context.fill(); + } + }; + break; + case 'meter': + // 绘制温度计数据图 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meterBorder); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + //画背景颜色 + context.beginPath(); + if (seriesIndex == 0 && columnOption.meterBorder > 0) { + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(columnOption.meterBorder * opts.pix); + } + if(seriesIndex == 0){ + context.setFillStyle(columnOption.meterFillColor); + }else{ + context.setFillStyle(item.color || eachSeries.color); + } + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { + const left = startX; + const top = item.y; + const width = item.width; + const height = zeroPoints - item.y; + if (columnOption.barBorderCircle) { + columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; + } + let [r0, r1, r2, r3] = columnOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + context.fill(); + }else{ + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); + context.lineTo(startX, item.y); + context.fill(); + } + if (seriesIndex == 0 && columnOption.meterBorder > 0) { + context.closePath(); + context.stroke(); + } + } + } + break; + } + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); + drawColumePointText(points, eachSeries, config, context, opts); + break; + case 'stack': + var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + drawColumePointText(points, eachSeries, config, context, opts); + break; + case 'meter': + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawColumePointText(points, eachSeries, config, context, opts); + break; + } + }); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawMountDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let mountOption = assign({}, { + type: 'mount', + widthRatio: 1, + borderWidth: 1, + barBorderCircle: false, + barBorderRadius: [], + linearType: 'none', + linearOpacity: 1, + customColor: [], + colorStop: 0, + }, opts.extra.mount); + mountOption.widthRatio = mountOption.widthRatio <= 0 ? 0 : mountOption.widthRatio; + mountOption.widthRatio = mountOption.widthRatio >= 2 ? 2 : mountOption.widthRatio; + let calPoints = []; + context.save(); + let leftNum = -2; + let rightNum = xAxisPoints.length + 2; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2; + rightNum = leftNum + opts.xAxis.itemCount + 4; + } + mountOption.customColor = fillCustomColor(mountOption.linearType, mountOption.customColor, series, config); + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[0]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + + // 计算0轴坐标 + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange); + let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2]; + + var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, process); + switch (mountOption.type) { + case 'bar': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + // 圆角边框 + if ((mountOption.barBorderRadius && mountOption.barBorderRadius.length === 4) || mountOption.barBorderCircle === true) { + const left = startX; + const top = item.y > zeroPoints ? zeroPoints : item.y; + const width = item.width; + const height = Math.abs(zeroPoints - item.y); + if (mountOption.barBorderCircle) { + mountOption.barBorderRadius = [width / 2, width / 2, 0, 0]; + } + if(item.y > zeroPoints){ + mountOption.barBorderRadius = [0, 0,width / 2, width / 2]; + } + let [r0, r1, r2, r3] = mountOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + } else { + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); + context.lineTo(startX, item.y); + } + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.closePath(); + context.stroke(); + } + context.fill(); + } + }; + break; + case 'triangle': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + context.moveTo(startX, zeroPoints); + context.lineTo(item.x, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + case 'mount': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + context.moveTo(startX, zeroPoints); + context.bezierCurveTo(item.x - item.width/4, zeroPoints, item.x - item.width/4, item.y, item.x, item.y); + context.bezierCurveTo(item.x + item.width/4, item.y, item.x + item.width/4, zeroPoints, startX + item.width, zeroPoints); + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + case 'sharp': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + context.moveTo(startX, zeroPoints); + context.quadraticCurveTo(item.x - 0, zeroPoints - height/4, item.x, item.y); + context.quadraticCurveTo(item.x + 0, zeroPoints - height/4, startX + item.width, zeroPoints) + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + } + + if (opts.dataLabel !== false && process === 1) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[0]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, process); + drawMountPointText(points, series, config, context, opts, zeroPoints); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: points, + eachSpacing: eachSpacing + }; +} + +function drawBarDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let yAxisPoints = []; + let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/opts.categories.length; + for (let i = 0; i < opts.categories.length; i++) { + yAxisPoints.push(opts.area[0] + eachSpacing / 2 + eachSpacing * i); + } + let columnOption = assign({}, { + type: 'group', + width: eachSpacing / 2, + meterBorder: 4, + meterFillColor: '#FFFFFF', + barBorderCircle: false, + barBorderRadius: [], + seriesGap: 2, + linearType: 'none', + linearOpacity: 1, + customColor: [], + colorStop: 0, + }, opts.extra.bar); + let calPoints = []; + context.save(); + let leftNum = -2; + let rightNum = yAxisPoints.length + 2; + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawBarToolTipSplitArea(opts.tooltip.offset.y, opts, config, context, eachSpacing); + } + columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config); + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.xAxisData.ranges); + maxRange = ranges.pop(); + minRange = ranges.shift(); + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, process); + var tooltipPoints = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + calPoints.push(tooltipPoints); + points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + //fix issues/I27B1N yyoinge & Joeshu + if (item !== null && i > leftNum && i < rightNum) { + //var startX = item.x - item.width / 2; + var startX = opts.area[3]; + var startY = item.y - item.width / 2; + var height = item.height; + context.beginPath(); + var fillColor = item.color || eachSeries.color + var strokeColor = item.color || eachSeries.color + if (columnOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, item.x, item.y); + //透明渐变 + if (columnOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity)); + grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + // 圆角边框 + if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { + const left = startX; + const width = item.width; + const top = item.y - item.width / 2; + const height = item.height; + if (columnOption.barBorderCircle) { + columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; + } + let [r0, r1, r2, r3] = columnOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + + context.arc(left + r3, top + r3, r3, -Math.PI, -Math.PI / 2); + context.arc(item.x - r0, top + r0, r0, -Math.PI / 2, 0); + context.arc(item.x - r1, top + width - r1, r1, 0, Math.PI / 2); + context.arc(left + r2, top + width - r2, r2, Math.PI / 2, Math.PI); + } else { + context.moveTo(startX, startY); + context.lineTo(item.x, startY); + context.lineTo(item.x, startY + item.width); + context.lineTo(startX, startY + item.width); + context.lineTo(startX, startY); + context.setLineWidth(1) + context.setStrokeStyle(strokeColor); + } + context.setFillStyle(fillColor); + context.closePath(); + //context.stroke(); + context.fill(); + } + }; + break; + case 'stack': + // 绘制堆叠数据图 + var points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + calPoints.push(points); + points = fixBarStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + context.beginPath(); + var fillColor = item.color || eachSeries.color; + var startX = item.x0; + context.setFillStyle(fillColor); + context.moveTo(startX, item.y - item.width/2); + context.fillRect(startX, item.y - item.width/2, item.height , item.width); + context.closePath(); + context.fill(); + } + }; + break; + } + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.xAxisData.ranges); + maxRange = ranges.pop(); + minRange = ranges.shift(); + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, process); + points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts); + drawBarPointText(points, eachSeries, config, context, opts); + break; + case 'stack': + var points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + drawBarPointText(points, eachSeries, config, context, opts); + break; + } + }); + } + return { + yAxisPoints: yAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawCandleDataPoints(series, seriesMA, opts, config, context) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + var candleOption = assign({}, { + color: {}, + average: {} + }, opts.extra.candle); + candleOption.color = assign({}, { + upLine: '#f04864', + upFill: '#f04864', + downLine: '#2fc25b', + downFill: '#2fc25b' + }, candleOption.color); + candleOption.average = assign({}, { + show: false, + name: [], + day: [], + color: config.color + }, candleOption.average); + opts.extra.candle = candleOption; + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let calPoints = []; + context.save(); + let leftNum = -2; + let rightNum = xAxisPoints.length + 2; + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2; + rightNum = leftNum + opts.xAxis.itemCount + 4; + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + //画均线 + if (candleOption.average.show || seriesMA) { //Merge pull request !12 from 邱贵翔 + seriesMA.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + var splitPointList = splitPoints(points,eachSeries); + for (let i = 0; i < splitPointList.length; i++) { + let points = splitPointList[i]; + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(1); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + let startPoint = 0; + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + var ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, + item.y); + } + } + context.moveTo(points[0].x, points[0].y); + } + context.closePath(); + context.stroke(); + } + }); + } + //画K线 + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + var splitPointList = splitPoints(points,eachSeries); + for (let i = 0; i < splitPointList[0].length; i++) { + if (i > leftNum && i < rightNum) { + let item = splitPointList[0][i]; + context.beginPath(); + //如果上涨 + if (data[i][1] - data[i][0] > 0) { + context.setStrokeStyle(candleOption.color.upLine); + context.setFillStyle(candleOption.color.upFill); + context.setLineWidth(1 * opts.pix); + context.moveTo(item[3].x, item[3].y); //顶点 + context.lineTo(item[1].x, item[1].y); //收盘中间点 + context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点 + context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点 + context.lineTo(item[0].x, item[0].y); //开盘中间点 + context.lineTo(item[2].x, item[2].y); //底点 + context.lineTo(item[0].x, item[0].y); //开盘中间点 + context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点 + context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点 + context.lineTo(item[1].x, item[1].y); //收盘中间点 + context.moveTo(item[3].x, item[3].y); //顶点 + } else { + context.setStrokeStyle(candleOption.color.downLine); + context.setFillStyle(candleOption.color.downFill); + context.setLineWidth(1 * opts.pix); + context.moveTo(item[3].x, item[3].y); //顶点 + context.lineTo(item[0].x, item[0].y); //开盘中间点 + context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点 + context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点 + context.lineTo(item[1].x, item[1].y); //收盘中间点 + context.lineTo(item[2].x, item[2].y); //底点 + context.lineTo(item[1].x, item[1].y); //收盘中间点 + context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点 + context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点 + context.lineTo(item[0].x, item[0].y); //开盘中间点 + context.moveTo(item[3].x, item[3].y); //顶点 + } + context.closePath(); + context.fill(); + context.stroke(); + } + } + }); + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawAreaDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var areaOption = assign({}, { + type: 'straight', + opacity: 0.2, + addLine: false, + width: 2, + gradient: false, + activeType: 'none' + }, opts.extra.area); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let endY = opts.height - opts.area[2]; + let calPoints = []; + context.save(); + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + let data = eachSeries.data; + let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + let splitPointList = splitPoints(points,eachSeries); + for (let i = 0; i < splitPointList.length; i++) { + let points = splitPointList[i]; + // 绘制区域数 + context.beginPath(); + context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + if (areaOption.gradient) { + let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height - opts.area[2]); + gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity)); + gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1)); + context.setFillStyle(gradient); + } else { + context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + } + context.setLineWidth(areaOption.width * opts.pix); + if (points.length > 1) { + let firstPoint = points[0]; + let lastPoint = points[points.length - 1]; + context.moveTo(firstPoint.x, firstPoint.y); + let startPoint = 0; + if (areaOption.type === 'curve') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + let ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); + } + }; + } + if (areaOption.type === 'straight') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, item.y); + } + }; + } + if (areaOption.type === 'step') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, points[j - 1].y); + context.lineTo(item.x, item.y); + } + }; + } + context.lineTo(lastPoint.x, endY); + context.lineTo(firstPoint.x, endY); + context.lineTo(firstPoint.x, firstPoint.y); + } else { + let item = points[0]; + context.moveTo(item.x - eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, endY); + // context.lineTo(item.x - eachSpacing / 2, endY); + // context.moveTo(item.x - eachSpacing / 2, item.y); + } + context.closePath(); + context.fill(); + //画连线 + if (areaOption.addLine) { + if (eachSeries.lineType == 'dash') { + let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8; + dashLength *= opts.pix; + context.setLineDash([dashLength, dashLength]); + } + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(areaOption.width * opts.pix); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + let startPoint = 0; + if (areaOption.type === 'curve') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + let ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); + } + }; + } + if (areaOption.type === 'straight') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, item.y); + } + }; + } + if (areaOption.type === 'step') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, points[j - 1].y); + context.lineTo(item.x, item.y); + } + }; + } + context.moveTo(points[0].x, points[0].y); + } + context.stroke(); + context.setLineDash([]); + } + } + //画点 + if (opts.dataPointShape !== false) { + drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); + } + drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, areaOption,seriesIndex); + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context, opts); + }); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawScatterDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var scatterOption = assign({}, { + type: 'circle' + }, opts.extra.scatter); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + var calPoints = []; + context.save(); + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setFillStyle(eachSeries.color); + context.setLineWidth(1 * opts.pix); + var shape = eachSeries.pointShape; + if (shape === 'diamond') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y); + context.lineTo(item.x, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'circle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x + 2.5 * opts.pix, item.y); + context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false); + } + }); + } else if (shape === 'square') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x - 3.5, item.y - 3.5); + context.rect(item.x - 3.5, item.y - 3.5, 7, 7); + } + }); + } else if (shape === 'triangle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y + 4.5); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'triangle') { + return; + } + context.closePath(); + context.fill(); + context.stroke(); + }); + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context, opts); + }); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawBubbleDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var bubbleOption = assign({}, { + opacity: 1, + border:2 + }, opts.extra.bubble); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + var calPoints = []; + context.save(); + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(bubbleOption.border * opts.pix); + context.setFillStyle(hexToRgb(eachSeries.color, bubbleOption.opacity)); + points.forEach(function(item, index) { + context.moveTo(item.x + item.r, item.y); + context.arc(item.x, item.y, item.r * opts.pix, 0, 2 * Math.PI, false); + }); + context.closePath(); + context.fill(); + context.stroke(); + + if (opts.dataLabel !== false && process === 1) { + points.forEach(function(item, index) { + context.beginPath(); + var fontSize = eachSeries.textSize * opts.pix || config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(eachSeries.textColor || "#FFFFFF"); + context.setTextAlign('center'); + context.fillText(String(item.t), item.x, item.y + fontSize/2); + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + }); + } + }); + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawLineDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var lineOption = assign({}, { + type: 'straight', + width: 2, + activeType: 'none', + linearType: 'none', + onShadow: false, + animation: 'vertical', + }, opts.extra.line); + lineOption.width *= opts.pix; + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + var calPoints = []; + context.save(); + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + series.forEach(function(eachSeries, seriesIndex) { + // 这段很神奇的代码用于解决ios16的setStrokeStyle失效的bug + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.moveTo(-10000, -10000); + context.lineTo(-10001, -10001); + context.stroke(); + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process); + calPoints.push(points); + var splitPointList = splitPoints(points,eachSeries); + if (eachSeries.lineType == 'dash') { + let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8; + dashLength *= opts.pix; + context.setLineDash([dashLength, dashLength]); + } + context.beginPath(); + var strokeColor = eachSeries.color; + if (lineOption.linearType !== 'none' && eachSeries.linearColor && eachSeries.linearColor.length > 0) { + var grd = context.createLinearGradient(opts.chartData.xAxisData.startX, opts.height/2, opts.chartData.xAxisData.endX, opts.height/2); + for (var i = 0; i < eachSeries.linearColor.length; i++) { + grd.addColorStop(eachSeries.linearColor[i][0], hexToRgb(eachSeries.linearColor[i][1], 1)); + } + strokeColor = grd + } + context.setStrokeStyle(strokeColor); + if (lineOption.onShadow == true && eachSeries.setShadow && eachSeries.setShadow.length > 0) { + context.setShadow(eachSeries.setShadow[0], eachSeries.setShadow[1], eachSeries.setShadow[2], eachSeries.setShadow[3]); + }else{ + context.setShadow(0, 0, 0, 'rgba(0,0,0,0)'); + } + context.setLineWidth(lineOption.width); + splitPointList.forEach(function(points, index) { + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + let startPoint = 0; + if (lineOption.type === 'curve') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + var ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); + } + }; + } + if (lineOption.type === 'straight') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, item.y); + } + }; + } + if (lineOption.type === 'step') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, points[j - 1].y); + context.lineTo(item.x, item.y); + } + }; + } + context.moveTo(points[0].x, points[0].y); + } + }); + context.stroke(); + context.setLineDash([]); + if (opts.dataPointShape !== false) { + drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); + } + drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, lineOption); + }); + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context, opts); + }); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing + }; +} + +function drawMixDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let columnOption = assign({}, { + width: eachSpacing / 2, + barBorderCircle: false, + barBorderRadius: [], + seriesGap: 2, + linearType: 'none', + linearOpacity: 1, + customColor: [], + colorStop: 0, + }, opts.extra.mix.column); + let areaOption = assign({}, { + opacity: 0.2, + gradient: false + }, opts.extra.mix.area); + let lineOption = assign({}, { + width: 2 + }, opts.extra.mix.line); + let endY = opts.height - opts.area[2]; + let calPoints = []; + var columnIndex = 0; + var columnLength = 0; + series.forEach(function(eachSeries, seriesIndex) { + if (eachSeries.type == 'column') { + columnLength += 1; + } + }); + context.save(); + let leftNum = -2; + let rightNum = xAxisPoints.length + 2; + let leftSpace = 0; + let rightSpace = opts.width + eachSpacing; + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2; + rightNum = leftNum + opts.xAxis.itemCount + 4; + leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3]; + rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; + } + columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config); + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + // 绘制柱状数据图 + if (eachSeries.type == 'column') { + points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || eachSeries.color + var strokeColor = item.color || eachSeries.color + if (columnOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); + //透明渐变 + if (columnOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity)); + grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + // 圆角边框 + if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle) { + const left = startX; + const top = item.y; + const width = item.width; + const height = opts.height - opts.area[2] - item.y; + if (columnOption.barBorderCircle) { + columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; + } + let [r0, r1, r2, r3] = columnOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + } else { + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, opts.height - opts.area[2]); + context.lineTo(startX, opts.height - opts.area[2]); + context.lineTo(startX, item.y); + context.setLineWidth(1) + context.setStrokeStyle(strokeColor); + } + context.setFillStyle(fillColor); + context.closePath(); + context.fill(); + } + } + columnIndex += 1; + } + //绘制区域图数据 + if (eachSeries.type == 'area') { + let splitPointList = splitPoints(points,eachSeries); + for (let i = 0; i < splitPointList.length; i++) { + let points = splitPointList[i]; + // 绘制区域数据 + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + if (areaOption.gradient) { + let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height - opts.area[2]); + gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity)); + gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1)); + context.setFillStyle(gradient); + } else { + context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + } + context.setLineWidth(2 * opts.pix); + if (points.length > 1) { + var firstPoint = points[0]; + let lastPoint = points[points.length - 1]; + context.moveTo(firstPoint.x, firstPoint.y); + let startPoint = 0; + if (eachSeries.style === 'curve') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + var ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); + } + }; + } else { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, item.y); + } + }; + } + context.lineTo(lastPoint.x, endY); + context.lineTo(firstPoint.x, endY); + context.lineTo(firstPoint.x, firstPoint.y); + } else { + let item = points[0]; + context.moveTo(item.x - eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, endY); + // context.lineTo(item.x - eachSpacing / 2, endY); + // context.moveTo(item.x - eachSpacing / 2, item.y); + } + context.closePath(); + context.fill(); + } + } + // 绘制折线数据图 + if (eachSeries.type == 'line') { + var splitPointList = splitPoints(points,eachSeries); + splitPointList.forEach(function(points, index) { + if (eachSeries.lineType == 'dash') { + let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8; + dashLength *= opts.pix; + context.setLineDash([dashLength, dashLength]); + } + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(lineOption.width * opts.pix); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + let startPoint = 0; + if (eachSeries.style == 'curve') { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + var ctrlPoint = createCurveControlPoints(points, j - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, item.y); + } + } + } else { + for (let j = 0; j < points.length; j++) { + let item = points[j]; + if (startPoint == 0 && item.x > leftSpace) { + context.moveTo(item.x, item.y); + startPoint = 1; + } + if (j > 0 && item.x > leftSpace && item.x < rightSpace) { + context.lineTo(item.x, item.y); + } + } + } + context.moveTo(points[0].x, points[0].y); + } + context.stroke(); + context.setLineDash([]); + }); + } + // 绘制点数据图 + if (eachSeries.type == 'point') { + eachSeries.addPoint = true; + } + if (eachSeries.addPoint == true && eachSeries.type !== 'column') { + drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); + } + }); + if (opts.dataLabel !== false && process === 1) { + var columnIndex = 0; + series.forEach(function(eachSeries, seriesIndex) { + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + if (eachSeries.type !== 'column') { + drawPointText(points, eachSeries, config, context, opts); + } else { + points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts); + drawPointText(points, eachSeries, config, context, opts); + columnIndex += 1; + } + }); + } + context.restore(); + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + } +} + + +function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) { + var toolTipOption = opts.extra.tooltip || {}; + if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'mount' || opts.type == 'candle' || opts.type == 'mix')) { + drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) + } + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints); + } + context.restore(); + +} + +function drawXAxis(categories, opts, config, context) { + + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + startX = xAxisData.startX, + endX = xAxisData.endX, + eachSpacing = xAxisData.eachSpacing; + var boundaryGap = 'center'; + if (opts.type == 'bar' || opts.type == 'line' || opts.type == 'area'|| opts.type == 'scatter' || opts.type == 'bubble') { + boundaryGap = opts.xAxis.boundaryGap; + } + var startY = opts.height - opts.area[2]; + var endY = opts.area[0]; + + //绘制滚动条 + if (opts.enableScroll && opts.xAxis.scrollShow) { + var scrollY = opts.height - opts.area[2] + config.xAxisHeight; + var scrollScreenWidth = endX - startX; + var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1); + if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){ + if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2 + scrollTotalWidth += (opts.extra.mount.widthRatio - 1)*eachSpacing; + } + var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth; + var scrollLeft = 0; + if (opts._scrollDistance_) { + scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth; + } + context.beginPath(); + context.setLineCap('round'); + context.setLineWidth(6 * opts.pix); + context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF"); + context.moveTo(startX, scrollY); + context.lineTo(endX, scrollY); + context.stroke(); + context.closePath(); + context.beginPath(); + context.setLineCap('round'); + context.setLineWidth(6 * opts.pix); + context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6"); + context.moveTo(startX + scrollLeft, scrollY); + context.lineTo(startX + scrollLeft + scrollWidth, scrollY); + context.stroke(); + context.closePath(); + context.setLineCap('butt'); + } + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) { + context.translate(opts._scrollDistance_, 0); + } + //绘制X轴刻度线 + if (opts.xAxis.calibration === true) { + context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc"); + context.setLineCap('butt'); + context.setLineWidth(1 * opts.pix); + xAxisPoints.forEach(function(item, index) { + if (index > 0) { + context.beginPath(); + context.moveTo(item - eachSpacing / 2, startY); + context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pix); + context.closePath(); + context.stroke(); + } + }); + } + //绘制X轴网格 + if (opts.xAxis.disableGrid !== true) { + context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc"); + context.setLineCap('butt'); + context.setLineWidth(1 * opts.pix); + if (opts.xAxis.gridType == 'dash') { + context.setLineDash([opts.xAxis.dashLength * opts.pix, opts.xAxis.dashLength * opts.pix]); + } + opts.xAxis.gridEval = opts.xAxis.gridEval || 1; + xAxisPoints.forEach(function(item, index) { + if (index % opts.xAxis.gridEval == 0) { + context.beginPath(); + context.moveTo(item, startY); + context.lineTo(item, endY); + context.stroke(); + } + }); + context.setLineDash([]); + } + //绘制X轴文案 + if (opts.xAxis.disabled !== true) { + // 对X轴列表做抽稀处理 + //默认全部显示X轴标签 + let maxXAxisListLength = categories.length; + //如果设置了X轴单屏数量 + if (opts.xAxis.labelCount) { + //如果设置X轴密度 + if (opts.xAxis.itemCount) { + maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount); + } else { + maxXAxisListLength = opts.xAxis.labelCount; + } + maxXAxisListLength -= 1; + } + + let ratio = Math.ceil(categories.length / maxXAxisListLength); + + let newCategories = []; + let cgLength = categories.length; + for (let i = 0; i < cgLength; i++) { + if (i % ratio !== 0) { + newCategories.push(""); + } else { + newCategories.push(categories[i]); + } + } + newCategories[cgLength - 1] = categories[cgLength - 1]; + var xAxisFontSize = opts.xAxis.fontSize * opts.pix || config.fontSize; + if (config._xAxisTextAngle_ === 0) { + newCategories.forEach(function(item, index) { + var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item; + var offset = -measureText(String(xitem), xAxisFontSize, context) / 2; + if (boundaryGap == 'center') { + offset += eachSpacing / 2; + } + var scrollHeight = 0; + if (opts.xAxis.scrollShow) { + scrollHeight = 6 * opts.pix; + } + // 如果在主视图区域内 + var _scrollDistance_ = opts._scrollDistance_ || 0; + var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index]; + if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){ + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); + context.fillText(String(xitem), xAxisPoints[index] + offset, startY + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.fontSize) * opts.pix / 2 + opts.xAxis.fontSize * opts.pix); + context.closePath(); + context.stroke(); + } + }); + } else { + newCategories.forEach(function(item, index) { + var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item; + // 如果在主视图区域内 + var _scrollDistance_ = opts._scrollDistance_ || 0; + var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index]; + if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){ + context.save(); + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); + var textWidth = measureText(String(xitem), xAxisFontSize, context); + var offsetX = xAxisPoints[index]; + if (boundaryGap == 'center') { + offsetX = xAxisPoints[index] + eachSpacing / 2; + } + var scrollHeight = 0; + if (opts.xAxis.scrollShow) { + scrollHeight = 6 * opts.pix; + } + var offsetY = startY + opts.xAxis.marginTop * opts.pix + xAxisFontSize - xAxisFontSize * Math.abs(Math.sin(config._xAxisTextAngle_)); + if(opts.xAxis.rotateAngle < 0){ + offsetX -= xAxisFontSize / 2; + textWidth = 0; + }else{ + offsetX += xAxisFontSize / 2; + textWidth = -textWidth; + } + context.translate(offsetX, offsetY); + context.rotate(-1 * config._xAxisTextAngle_); + context.fillText(String(xitem), textWidth , 0 ); + context.closePath(); + context.stroke(); + context.restore(); + } + }); + } + } + context.restore(); + + //画X轴标题 + if (opts.xAxis.title) { + context.beginPath(); + context.setFontSize(opts.xAxis.titleFontSize * opts.pix); + context.setFillStyle(opts.xAxis.titleFontColor); + context.fillText(String(opts.xAxis.title), opts.width - opts.area[1] + opts.xAxis.titleOffsetX * opts.pix,opts.height - opts.area[2] + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.titleFontSize) * opts.pix / 2 + (opts.xAxis.titleFontSize + opts.xAxis.titleOffsetY) * opts.pix); + context.closePath(); + context.stroke(); + } + + //绘制X轴轴线 + if (opts.xAxis.axisLine) { + context.beginPath(); + context.setStrokeStyle(opts.xAxis.axisLineColor); + context.setLineWidth(1 * opts.pix); + context.moveTo(startX, opts.height - opts.area[2]); + context.lineTo(endX, opts.height - opts.area[2]); + context.stroke(); + } +} + +function drawYAxisGrid(categories, opts, config, context) { + if (opts.yAxis.disableGrid === true) { + return; + } + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let eachSpacing = spacingValid / opts.yAxis.splitNumber; + let startX = opts.area[3]; + let xAxisPoints = opts.chartData.xAxisData.xAxisPoints, + xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing; + let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1); + if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1 ){ + if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2 + TotalWidth += (opts.extra.mount.widthRatio - 1) * xAxiseachSpacing; + } + let endX = startX + TotalWidth; + let points = []; + let startY = 1 + if (opts.xAxis.axisLine === false) { + startY = 0 + } + for (let i = startY; i < opts.yAxis.splitNumber + 1; i++) { + points.push(opts.height - opts.area[2] - eachSpacing * i); + } + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) { + context.translate(opts._scrollDistance_, 0); + } + if (opts.yAxis.gridType == 'dash') { + context.setLineDash([opts.yAxis.dashLength * opts.pix, opts.yAxis.dashLength * opts.pix]); + } + context.setStrokeStyle(opts.yAxis.gridColor); + context.setLineWidth(1 * opts.pix); + points.forEach(function(item, index) { + context.beginPath(); + context.moveTo(startX, item); + context.lineTo(endX, item); + context.stroke(); + }); + context.setLineDash([]); + context.restore(); +} + +function drawYAxis(series, opts, config, context) { + if (opts.yAxis.disabled === true) { + return; + } + var spacingValid = opts.height - opts.area[0] - opts.area[2]; + var eachSpacing = spacingValid / opts.yAxis.splitNumber; + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + var endY = opts.height - opts.area[2]; + // set YAxis background + context.beginPath(); + context.setFillStyle(opts.background); + if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'left') { + context.fillRect(0, 0, startX, endY + 2 * opts.pix); + } + if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'right') { + context.fillRect(endX, 0, opts.width, endY + 2 * opts.pix); + } + context.closePath(); + context.stroke(); + + let tStartLeft = opts.area[3]; + let tStartRight = opts.width - opts.area[1]; + let tStartCenter = opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2; + if (opts.yAxis.data) { + for (let i = 0; i < opts.yAxis.data.length; i++) { + let yData = opts.yAxis.data[i]; + var points = []; + if(yData.type === 'categories'){ + for (let i = 0; i <= yData.categories.length; i++) { + points.push(opts.area[0] + spacingValid / yData.categories.length / 2 + spacingValid / yData.categories.length * i); + } + }else{ + for (let i = 0; i <= opts.yAxis.splitNumber; i++) { + points.push(opts.area[0] + eachSpacing * i); + } + } + if (yData.disabled !== true) { + let rangesFormat = opts.chartData.yAxisData.rangesFormat[i]; + let yAxisFontSize = yData.fontSize ? yData.fontSize * opts.pix : config.fontSize; + let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i]; + let textAlign = yData.textAlign || "right"; + //画Y轴刻度及文案 + rangesFormat.forEach(function(item, index) { + var pos = points[index]; + context.beginPath(); + context.setFontSize(yAxisFontSize); + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(yData.axisLineColor || '#cccccc'); + context.setFillStyle(yData.fontColor || opts.fontColor); + let tmpstrat = 0; + let gapwidth = 4 * opts.pix; + if (yAxisWidth.position == 'left') { + //画刻度线 + if (yData.calibration == true) { + context.moveTo(tStartLeft, pos); + context.lineTo(tStartLeft - 3 * opts.pix, pos); + gapwidth += 3 * opts.pix; + } + //画文字 + switch (textAlign) { + case "left": + context.setTextAlign('left'); + tmpstrat = tStartLeft - yAxisWidth.width + break; + case "right": + context.setTextAlign('right'); + tmpstrat = tStartLeft - gapwidth + break; + default: + context.setTextAlign('center'); + tmpstrat = tStartLeft - yAxisWidth.width / 2 + } + context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix); + + } else if (yAxisWidth.position == 'right') { + //画刻度线 + if (yData.calibration == true) { + context.moveTo(tStartRight, pos); + context.lineTo(tStartRight + 3 * opts.pix, pos); + gapwidth += 3 * opts.pix; + } + switch (textAlign) { + case "left": + context.setTextAlign('left'); + tmpstrat = tStartRight + gapwidth + break; + case "right": + context.setTextAlign('right'); + tmpstrat = tStartRight + yAxisWidth.width + break; + default: + context.setTextAlign('center'); + tmpstrat = tStartRight + yAxisWidth.width / 2 + } + context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix); + } else if (yAxisWidth.position == 'center') { + //画刻度线 + if (yData.calibration == true) { + context.moveTo(tStartCenter, pos); + context.lineTo(tStartCenter - 3 * opts.pix, pos); + gapwidth += 3 * opts.pix; + } + //画文字 + switch (textAlign) { + case "left": + context.setTextAlign('left'); + tmpstrat = tStartCenter - yAxisWidth.width + break; + case "right": + context.setTextAlign('right'); + tmpstrat = tStartCenter - gapwidth + break; + default: + context.setTextAlign('center'); + tmpstrat = tStartCenter - yAxisWidth.width / 2 + } + context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix); + } + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + }); + //画Y轴轴线 + if (yData.axisLine !== false) { + context.beginPath(); + context.setStrokeStyle(yData.axisLineColor || '#cccccc'); + context.setLineWidth(1 * opts.pix); + if (yAxisWidth.position == 'left') { + context.moveTo(tStartLeft, opts.height - opts.area[2]); + context.lineTo(tStartLeft, opts.area[0]); + } else if (yAxisWidth.position == 'right') { + context.moveTo(tStartRight, opts.height - opts.area[2]); + context.lineTo(tStartRight, opts.area[0]); + } else if (yAxisWidth.position == 'center') { + context.moveTo(tStartCenter, opts.height - opts.area[2]); + context.lineTo(tStartCenter, opts.area[0]); + } + context.stroke(); + } + //画Y轴标题 + if (opts.yAxis.showTitle) { + let titleFontSize = yData.titleFontSize * opts.pix || config.fontSize; + let title = yData.title; + context.beginPath(); + context.setFontSize(titleFontSize); + context.setFillStyle(yData.titleFontColor || opts.fontColor); + if (yAxisWidth.position == 'left') { + context.fillText(title, tStartLeft - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix); + } else if (yAxisWidth.position == 'right') { + context.fillText(title, tStartRight - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix); + } else if (yAxisWidth.position == 'center') { + context.fillText(title, tStartCenter - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix); + } + context.closePath(); + context.stroke(); + } + if (yAxisWidth.position == 'left') { + tStartLeft -= (yAxisWidth.width + opts.yAxis.padding * opts.pix); + } else { + tStartRight += yAxisWidth.width + opts.yAxis.padding * opts.pix; + } + } + } + } + +} + +function drawLegend(series, opts, config, context, chartData) { + if (opts.legend.show === false) { + return; + } + let legendData = chartData.legendData; + let legendList = legendData.points; + let legendArea = legendData.area; + let padding = opts.legend.padding * opts.pix; + let fontSize = opts.legend.fontSize * opts.pix; + let shapeWidth = 15 * opts.pix; + let shapeRight = 5 * opts.pix; + let itemGap = opts.legend.itemGap * opts.pix; + let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize); + //画背景及边框 + context.beginPath(); + context.setLineWidth(opts.legend.borderWidth * opts.pix); + context.setStrokeStyle(opts.legend.borderColor); + context.setFillStyle(opts.legend.backgroundColor); + context.moveTo(legendArea.start.x, legendArea.start.y); + context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height); + context.closePath(); + context.fill(); + context.stroke(); + legendList.forEach(function(itemList, listIndex) { + let width = 0; + let height = 0; + width = legendData.widthArr[listIndex]; + height = legendData.heightArr[listIndex]; + let startX = 0; + let startY = 0; + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + switch (opts.legend.float) { + case 'left': + startX = legendArea.start.x + padding; + break; + case 'right': + startX = legendArea.start.x + legendArea.width - width; + break; + default: + startX = legendArea.start.x + (legendArea.width - width) / 2; + } + startY = legendArea.start.y + padding + listIndex * lineHeight; + } else { + if (listIndex == 0) { + width = 0; + } else { + width = legendData.widthArr[listIndex - 1]; + } + startX = legendArea.start.x + padding + width; + startY = legendArea.start.y + padding + (legendArea.height - height) / 2; + } + context.setFontSize(config.fontSize); + for (let i = 0; i < itemList.length; i++) { + let item = itemList[i]; + item.area = [0, 0, 0, 0]; + item.area[0] = startX; + item.area[1] = startY; + item.area[3] = startY + lineHeight; + context.beginPath(); + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor); + context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor); + switch (item.legendShape) { + case 'line': + context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pix); + context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pix, 15 * opts.pix, 4 * opts.pix); + break; + case 'triangle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix); + break; + case 'diamond': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix); + break; + case 'circle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight); + context.arc(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight, 5 * opts.pix, 0, 2 * Math.PI); + break; + case 'rect': + context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + break; + case 'square': + context.moveTo(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix); + context.fillRect(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix); + break; + case 'none': + break; + default: + context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + } + context.closePath(); + context.fill(); + context.stroke(); + startX += shapeWidth + shapeRight; + let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2; + const legendText = item.legendText ? item.legendText : item.name; + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor); + context.fillText(legendText, startX, startY + fontTrans); + context.closePath(); + context.stroke(); + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + startX += measureText(legendText, fontSize, context) + itemGap; + item.area[2] = startX; + } else { + item.area[2] = startX + measureText(legendText, fontSize, context) + itemGap;; + startX -= shapeWidth + shapeRight; + startY += lineHeight; + } + } + }); +} + +function drawPieDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var pieOption = assign({}, { + activeOpacity: 0.5, + activeRadius: 10, + offsetAngle: 0, + labelWidth: 15, + ringWidth: 30, + customRadius: 0, + border: false, + borderWidth: 2, + borderColor: '#FFFFFF', + centerColor: '#FFFFFF', + linearType: 'none', + customColor: [], + }, opts.type == "pie" ? opts.extra.pie : opts.extra.ring); + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + if (config.pieChartLinePadding == 0) { + config.pieChartLinePadding = pieOption.activeRadius * opts.pix; + } + + var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding); + radius = radius < 10 ? 10 : radius; + if (pieOption.customRadius > 0) { + radius = pieOption.customRadius * opts.pix; + } + series = getPieDataPoints(series, radius, process); + var activeRadius = pieOption.activeRadius * opts.pix; + pieOption.customColor = fillCustomColor(pieOption.linearType, pieOption.customColor, series, config); + series = series.map(function(eachSeries) { + eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180; + return eachSeries; + }); + series.forEach(function(eachSeries, seriesIndex) { + if (opts.tooltip) { + if (opts.tooltip.index == seriesIndex) { + context.beginPath(); + context.setFillStyle(hexToRgb(eachSeries.color, pieOption.activeOpacity || 0.5)); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + } + } + context.beginPath(); + context.setLineWidth(pieOption.borderWidth * opts.pix); + context.lineJoin = "round"; + context.setStrokeStyle(pieOption.borderColor); + var fillcolor = eachSeries.color; + if (pieOption.linearType == 'custom') { + var grd; + if(context.createCircularGradient){ + grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_) + }else{ + grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_) + } + grd.addColorStop(0, hexToRgb(pieOption.customColor[eachSeries.linearIndex], 1)) + grd.addColorStop(1, hexToRgb(eachSeries.color, 1)) + fillcolor = grd + } + context.setFillStyle(fillcolor); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + if (pieOption.border == true) { + context.stroke(); + } + }); + if (opts.type === 'ring') { + var innerPieWidth = radius * 0.6; + if (typeof pieOption.ringWidth === 'number' && pieOption.ringWidth > 0) { + innerPieWidth = Math.max(0, radius - pieOption.ringWidth * opts.pix); + } + context.beginPath(); + context.setFillStyle(pieOption.centerColor); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + } + if (opts.dataLabel !== false && process === 1) { + drawPieText(series, opts, config, context, radius, centerPosition); + } + if (process === 1 && opts.type === 'ring') { + drawRingTitle(opts, config, context, centerPosition); + } + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawRoseDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var roseOption = assign({}, { + type: 'area', + activeOpacity: 0.5, + activeRadius: 10, + offsetAngle: 0, + labelWidth: 15, + border: false, + borderWidth: 2, + borderColor: '#FFFFFF', + linearType: 'none', + customColor: [], + }, opts.extra.rose); + if (config.pieChartLinePadding == 0) { + config.pieChartLinePadding = roseOption.activeRadius * opts.pix; + } + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding); + radius = radius < 10 ? 10 : radius; + var minRadius = roseOption.minRadius || radius * 0.5; + if(radius < minRadius){ + radius = minRadius + 10; + } + series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process); + var activeRadius = roseOption.activeRadius * opts.pix; + roseOption.customColor = fillCustomColor(roseOption.linearType, roseOption.customColor, series, config); + series = series.map(function(eachSeries) { + eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180; + return eachSeries; + }); + series.forEach(function(eachSeries, seriesIndex) { + if (opts.tooltip) { + if (opts.tooltip.index == seriesIndex) { + context.beginPath(); + context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5)); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI); + context.closePath(); + context.fill(); + } + } + context.beginPath(); + context.setLineWidth(roseOption.borderWidth * opts.pix); + context.lineJoin = "round"; + context.setStrokeStyle(roseOption.borderColor); + var fillcolor = eachSeries.color; + if (roseOption.linearType == 'custom') { + var grd; + if(context.createCircularGradient){ + grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_) + }else{ + grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_) + } + grd.addColorStop(0, hexToRgb(roseOption.customColor[eachSeries.linearIndex], 1)) + grd.addColorStop(1, hexToRgb(eachSeries.color, 1)) + fillcolor = grd + } + context.setFillStyle(fillcolor); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI); + context.closePath(); + context.fill(); + if (roseOption.border == true) { + context.stroke(); + } + }); + + if (opts.dataLabel !== false && process === 1) { + drawPieText(series, opts, config, context, radius, centerPosition); + } + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawArcbarDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var arcbarOption = assign({}, { + startAngle: 0.75, + endAngle: 0.25, + type: 'default', + direction: 'cw', + lineCap: 'round', + width: 12 , + gap: 2 , + linearType: 'none', + customColor: [], + }, opts.extra.arcbar); + series = getArcbarDataPoints(series, arcbarOption, process); + var centerPosition; + if (arcbarOption.centerX || arcbarOption.centerY) { + centerPosition = { + x: arcbarOption.centerX ? arcbarOption.centerX : opts.width / 2, + y: arcbarOption.centerY ? arcbarOption.centerY : opts.height / 2 + }; + } else { + centerPosition = { + x: opts.width / 2, + y: opts.height / 2 + }; + } + var radius; + if (arcbarOption.radius) { + radius = arcbarOption.radius; + } else { + radius = Math.min(centerPosition.x, centerPosition.y); + radius -= 5 * opts.pix; + radius -= arcbarOption.width / 2; + } + radius = radius < 10 ? 10 : radius; + arcbarOption.customColor = fillCustomColor(arcbarOption.linearType, arcbarOption.customColor, series, config); + + for (let i = 0; i < series.length; i++) { + let eachSeries = series[i]; + //背景颜色 + context.setLineWidth(arcbarOption.width * opts.pix); + context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9'); + context.setLineCap(arcbarOption.lineCap); + context.beginPath(); + if (arcbarOption.type == 'default') { + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, arcbarOption.direction == 'ccw'); + } else { + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, arcbarOption.direction == 'ccw'); + } + context.stroke(); + //进度条 + var fillColor = eachSeries.color + if(arcbarOption.linearType == 'custom'){ + var grd = context.createLinearGradient(centerPosition.x - radius, centerPosition.y, centerPosition.x + radius, centerPosition.y); + grd.addColorStop(1, hexToRgb(arcbarOption.customColor[eachSeries.linearIndex], 1)) + grd.addColorStop(0, hexToRgb(eachSeries.color, 1)) + fillColor = grd; + } + context.setLineWidth(arcbarOption.width * opts.pix); + context.setStrokeStyle(fillColor); + context.setLineCap(arcbarOption.lineCap); + context.beginPath(); + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, arcbarOption.direction == 'ccw'); + context.stroke(); + } + drawRingTitle(opts, config, context, centerPosition); + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawGaugeDataPoints(categories, series, opts, config, context) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + var gaugeOption = assign({}, { + type: 'default', + startAngle: 0.75, + endAngle: 0.25, + width: 15, + labelOffset:13, + splitLine: { + fixRadius: 0, + splitNumber: 10, + width: 15, + color: '#FFFFFF', + childNumber: 5, + childWidth: 5 + }, + pointer: { + width: 15, + color: 'auto' + } + }, opts.extra.gauge); + if (gaugeOption.oldAngle == undefined) { + gaugeOption.oldAngle = gaugeOption.startAngle; + } + if (gaugeOption.oldData == undefined) { + gaugeOption.oldData = 0; + } + categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle); + var centerPosition = { + x: opts.width / 2, + y: opts.height / 2 + }; + var radius = Math.min(centerPosition.x, centerPosition.y); + radius -= 5 * opts.pix; + radius -= gaugeOption.width / 2; + radius = radius < 10 ? 10 : radius; + var innerRadius = radius - gaugeOption.width; + var totalAngle = 0; + //判断仪表盘的样式:default百度样式,progress新样式 + if (gaugeOption.type == 'progress') { + //## 第一步画中心圆形背景和进度条背景 + //中心圆形背景 + var pieRadius = radius - gaugeOption.width * 3; + context.beginPath(); + let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y - pieRadius, centerPosition.x, centerPosition.y + pieRadius); + //配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径) + gradient.addColorStop('0', hexToRgb(series[0].color, 0.3)); + gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1)); + context.setFillStyle(gradient); + context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2 * Math.PI, false); + context.fill(); + //画进度条背景 + context.setLineWidth(gaugeOption.width); + context.setStrokeStyle(hexToRgb(series[0].color, 0.3)); + context.setLineCap('round'); + context.beginPath(); + context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, gaugeOption.endAngle * Math.PI, false); + context.stroke(); + //## 第二步画刻度线 + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } + let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; + let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber; + let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius; + let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width; + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((gaugeOption.startAngle - 1) * Math.PI); + let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; + let proc = series[0].data * process; + for (let i = 0; i < len; i++) { + context.beginPath(); + //刻度线随进度变色 + if (proc > (i / len)) { + context.setStrokeStyle(hexToRgb(series[0].color, 1)); + } else { + context.setStrokeStyle(hexToRgb(series[0].color, 0.3)); + } + context.setLineWidth(3 * opts.pix); + context.moveTo(startX, 0); + context.lineTo(endX, 0); + context.stroke(); + context.rotate(childAngle * Math.PI); + } + context.restore(); + //## 第三步画进度条 + series = getGaugeArcbarDataPoints(series, gaugeOption, process); + context.setLineWidth(gaugeOption.width); + context.setStrokeStyle(series[0].color); + context.setLineCap('round'); + context.beginPath(); + context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, series[0]._proportion_ * Math.PI, false); + context.stroke(); + //## 第四步画指针 + let pointerRadius = radius - gaugeOption.width * 2.5; + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((series[0]._proportion_ - 1) * Math.PI); + context.beginPath(); + context.setLineWidth(gaugeOption.width / 3); + let gradient3 = context.createLinearGradient(0, -pointerRadius * 0.6, 0, pointerRadius * 0.6); + gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0)); + gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1)); + gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0)); + context.setStrokeStyle(gradient3); + context.arc(0, 0, pointerRadius, 0.85 * Math.PI, 1.15 * Math.PI, false); + context.stroke(); + context.beginPath(); + context.setLineWidth(1); + context.setStrokeStyle(series[0].color); + context.setFillStyle(series[0].color); + context.moveTo(-pointerRadius - gaugeOption.width / 3 / 2, -4); + context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2 - 4, 0); + context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, 4); + context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, -4); + context.stroke(); + context.fill(); + context.restore(); + //default百度样式 + } else { + //画背景 + context.setLineWidth(gaugeOption.width); + context.setLineCap('butt'); + for (let i = 0; i < categories.length; i++) { + let eachCategories = categories[i]; + context.beginPath(); + context.setStrokeStyle(eachCategories.color); + context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ * Math.PI, false); + context.stroke(); + } + context.save(); + //画刻度线 + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } + let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; + let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber; + let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius; + let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width; + let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth; + context.translate(centerPosition.x, centerPosition.y); + context.rotate((gaugeOption.startAngle - 1) * Math.PI); + for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) { + context.beginPath(); + context.setStrokeStyle(gaugeOption.splitLine.color); + context.setLineWidth(2 * opts.pix); + context.moveTo(startX, 0); + context.lineTo(endX, 0); + context.stroke(); + context.rotate(splitAngle * Math.PI); + } + context.restore(); + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((gaugeOption.startAngle - 1) * Math.PI); + for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) { + context.beginPath(); + context.setStrokeStyle(gaugeOption.splitLine.color); + context.setLineWidth(1 * opts.pix); + context.moveTo(startX, 0); + context.lineTo(childendX, 0); + context.stroke(); + context.rotate(childAngle * Math.PI); + } + context.restore(); + //画指针 + series = getGaugeDataPoints(series, categories, gaugeOption, process); + for (let i = 0; i < series.length; i++) { + let eachSeries = series[i]; + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((eachSeries._proportion_ - 1) * Math.PI); + context.beginPath(); + context.setFillStyle(eachSeries.color); + context.moveTo(gaugeOption.pointer.width, 0); + context.lineTo(0, -gaugeOption.pointer.width / 2); + context.lineTo(-innerRadius, 0); + context.lineTo(0, gaugeOption.pointer.width / 2); + context.lineTo(gaugeOption.pointer.width, 0); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFillStyle('#FFFFFF'); + context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false); + context.fill(); + context.restore(); + } + if (opts.dataLabel !== false) { + drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context); + } + } + //画仪表盘标题,副标题 + drawRingTitle(opts, config, context, centerPosition); + if (process === 1 && opts.type === 'gauge') { + opts.extra.gauge.oldAngle = series[0]._proportion_; + opts.extra.gauge.oldData = series[0].data; + } + return { + center: centerPosition, + radius: radius, + innerRadius: innerRadius, + categories: categories, + totalAngle: totalAngle + }; +} + +function drawRadarDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var radarOption = assign({}, { + gridColor: '#cccccc', + gridType: 'radar', + gridEval:1, + axisLabel:false, + axisLabelTofix:0, + labelShow:true, + labelColor:'#666666', + labelPointShow:false, + labelPointRadius:3, + labelPointColor:'#cccccc', + opacity: 0.2, + gridCount: 3, + border:false, + borderWidth:2, + linearType: 'none', + customColor: [], + }, opts.extra.radar); + var coordinateAngle = getRadarCoordinateSeries(opts.categories.length); + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + var xr = (opts.width - opts.area[1] - opts.area[3]) / 2 + var yr = (opts.height - opts.area[0] - opts.area[2]) / 2 + var radius = Math.min(xr - (getMaxTextListLength(opts.categories, config.fontSize, context) + config.radarLabelTextMargin), yr - config.radarLabelTextMargin); + radius -= config.radarLabelTextMargin * opts.pix; + radius = radius < 10 ? 10 : radius; + radius = radarOption.radius ? radarOption.radius : radius; + // 画分割线 + context.beginPath(); + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(radarOption.gridColor); + coordinateAngle.forEach(function(angle,index) { + var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition); + context.moveTo(centerPosition.x, centerPosition.y); + if (index % radarOption.gridEval == 0) { + context.lineTo(pos.x, pos.y); + } + }); + context.stroke(); + context.closePath(); + + // 画背景网格 + var _loop = function _loop(i) { + var startPos = {}; + context.beginPath(); + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(radarOption.gridColor); + if (radarOption.gridType == 'radar') { + coordinateAngle.forEach(function(angle, index) { + var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius / + radarOption.gridCount * i * Math.sin(angle), centerPosition); + if (index === 0) { + startPos = pos; + context.moveTo(pos.x, pos.y); + } else { + context.lineTo(pos.x, pos.y); + } + }); + context.lineTo(startPos.x, startPos.y); + } else { + var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(1.5), radius / radarOption.gridCount * i * Math.sin(1.5), centerPosition); + context.arc(centerPosition.x, centerPosition.y, centerPosition.y - pos.y, 0, 2 * Math.PI, false); + } + context.stroke(); + context.closePath(); + }; + for (var i = 1; i <= radarOption.gridCount; i++) { + _loop(i); + } + radarOption.customColor = fillCustomColor(radarOption.linearType, radarOption.customColor, series, config); + var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process); + radarDataPoints.forEach(function(eachSeries, seriesIndex) { + // 绘制区域数据 + context.beginPath(); + context.setLineWidth(radarOption.borderWidth * opts.pix); + context.setStrokeStyle(eachSeries.color); + + var fillcolor = hexToRgb(eachSeries.color, radarOption.opacity); + if (radarOption.linearType == 'custom') { + var grd; + if(context.createCircularGradient){ + grd = context.createCircularGradient(centerPosition.x, centerPosition.y, radius) + }else{ + grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, radius) + } + grd.addColorStop(0, hexToRgb(radarOption.customColor[series[seriesIndex].linearIndex], radarOption.opacity)) + grd.addColorStop(1, hexToRgb(eachSeries.color, radarOption.opacity)) + fillcolor = grd + } + + context.setFillStyle(fillcolor); + eachSeries.data.forEach(function(item, index) { + if (index === 0) { + context.moveTo(item.position.x, item.position.y); + } else { + context.lineTo(item.position.x, item.position.y); + } + }); + context.closePath(); + context.fill(); + if(radarOption.border === true){ + context.stroke(); + } + context.closePath(); + if (opts.dataPointShape !== false) { + var points = eachSeries.data.map(function(item) { + return item.position; + }); + drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); + } + }); + // 画刻度值 + if(radarOption.axisLabel === true){ + const maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series))); + const stepLength = radius / radarOption.gridCount; + const fontSize = opts.fontSize * opts.pix; + context.setFontSize(fontSize); + context.setFillStyle(opts.fontColor); + context.setTextAlign('left'); + for (var i = 0; i < radarOption.gridCount + 1; i++) { + let label = i * maxData / radarOption.gridCount; + label = label.toFixed(radarOption.axisLabelTofix); + context.fillText(String(label), centerPosition.x + 3 * opts.pix, centerPosition.y - i * stepLength + fontSize / 2); + } + } + + // draw label text + drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context); + + // draw dataLabel + if (opts.dataLabel !== false && process === 1) { + radarDataPoints.forEach(function(eachSeries, seriesIndex) { + context.beginPath(); + var fontSize = eachSeries.textSize * opts.pix || config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(eachSeries.textColor || opts.fontColor); + eachSeries.data.forEach(function(item, index) { + //如果是中心点垂直的上下点位 + if(Math.abs(item.position.x - centerPosition.x)<2){ + //如果在上面 + if(item.position.y < centerPosition.y){ + context.setTextAlign('center'); + context.fillText(item.value, item.position.x, item.position.y - 4); + }else{ + context.setTextAlign('center'); + context.fillText(item.value, item.position.x, item.position.y + fontSize + 2); + } + }else{ + //如果在左侧 + if(item.position.x < centerPosition.x){ + context.setTextAlign('right'); + context.fillText(item.value, item.position.x - 4, item.position.y + fontSize / 2 - 2); + }else{ + context.setTextAlign('left'); + context.fillText(item.value, item.position.x + 4, item.position.y + fontSize / 2 - 2); + } + } + }); + context.closePath(); + context.stroke(); + }); + context.setTextAlign('left'); + } + + return { + center: centerPosition, + radius: radius, + angleList: coordinateAngle + }; +} + +// 经纬度转墨卡托 +function lonlat2mercator(longitude, latitude) { + var mercator = Array(2); + var x = longitude * 20037508.34 / 180; + var y = Math.log(Math.tan((90 + latitude) * Math.PI / 360)) / (Math.PI / 180); + y = y * 20037508.34 / 180; + mercator[0] = x; + mercator[1] = y; + return mercator; +} + +// 墨卡托转经纬度 +function mercator2lonlat(longitude, latitude) { + var lonlat = Array(2) + var x = longitude / 20037508.34 * 180; + var y = latitude / 20037508.34 * 180; + y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2); + lonlat[0] = x; + lonlat[1] = y; + return lonlat; +} + +function getBoundingBox(data) { + var bounds = {},coords; + bounds.xMin = 180; + bounds.xMax = 0; + bounds.yMin = 90; + bounds.yMax = 0 + for (var i = 0; i < data.length; i++) { + var coorda = data[i].geometry.coordinates + for (var k = 0; k < coorda.length; k++) { + coords = coorda[k]; + if (coords.length == 1) { + coords = coords[0] + } + for (var j = 0; j < coords.length; j++) { + var longitude = coords[j][0]; + var latitude = coords[j][1]; + var point = { + x: longitude, + y: latitude + } + bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x; + bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x; + bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y; + bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y; + } + } + } + return bounds; +} + +function coordinateToPoint(latitude, longitude, bounds, scale, xoffset, yoffset) { + return { + x: (longitude - bounds.xMin) * scale + xoffset, + y: (bounds.yMax - latitude) * scale + yoffset + }; +} + +function pointToCoordinate(pointY, pointX, bounds, scale, xoffset, yoffset) { + return { + x: (pointX - xoffset) / scale + bounds.xMin, + y: bounds.yMax - (pointY - yoffset) / scale + }; +} + +function isRayIntersectsSegment(poi, s_poi, e_poi) { + if (s_poi[1] == e_poi[1]) { + return false; + } + if (s_poi[1] > poi[1] && e_poi[1] > poi[1]) { + return false; + } + if (s_poi[1] < poi[1] && e_poi[1] < poi[1]) { + return false; + } + if (s_poi[1] == poi[1] && e_poi[1] > poi[1]) { + return false; + } + if (e_poi[1] == poi[1] && s_poi[1] > poi[1]) { + return false; + } + if (s_poi[0] < poi[0] && e_poi[1] < poi[1]) { + return false; + } + let xseg = e_poi[0] - (e_poi[0] - s_poi[0]) * (e_poi[1] - poi[1]) / (e_poi[1] - s_poi[1]); + if (xseg < poi[0]) { + return false; + } else { + return true; + } +} + +function isPoiWithinPoly(poi, poly, mercator) { + let sinsc = 0; + for (let i = 0; i < poly.length; i++) { + let epoly = poly[i][0]; + if (poly.length == 1) { + epoly = poly[i][0] + } + for (let j = 0; j < epoly.length - 1; j++) { + let s_poi = epoly[j]; + let e_poi = epoly[j + 1]; + if (mercator) { + s_poi = lonlat2mercator(epoly[j][0], epoly[j][1]); + e_poi = lonlat2mercator(epoly[j + 1][0], epoly[j + 1][1]); + } + if (isRayIntersectsSegment(poi, s_poi, e_poi)) { + sinsc += 1; + } + } + } + if (sinsc % 2 == 1) { + return true; + } else { + return false; + } +} + +function drawMapDataPoints(series, opts, config, context) { + var mapOption = assign({}, { + border: true, + mercator: false, + borderWidth: 1, + active:true, + borderColor: '#666666', + fillOpacity: 0.6, + activeBorderColor: '#f04864', + activeFillColor: '#facc14', + activeFillOpacity: 1 + }, opts.extra.map); + var coords, point; + var data = series; + var bounds = getBoundingBox(data); + if (mapOption.mercator) { + var max = lonlat2mercator(bounds.xMax, bounds.yMax) + var min = lonlat2mercator(bounds.xMin, bounds.yMin) + bounds.xMax = max[0] + bounds.yMax = max[1] + bounds.xMin = min[0] + bounds.yMin = min[1] + } + var xScale = opts.width / Math.abs(bounds.xMax - bounds.xMin); + var yScale = opts.height / Math.abs(bounds.yMax - bounds.yMin); + var scale = xScale < yScale ? xScale : yScale; + var xoffset = opts.width / 2 - Math.abs(bounds.xMax - bounds.xMin) / 2 * scale; + var yoffset = opts.height / 2 - Math.abs(bounds.yMax - bounds.yMin) / 2 * scale; + for (var i = 0; i < data.length; i++) { + context.beginPath(); + context.setLineWidth(mapOption.borderWidth * opts.pix); + context.setStrokeStyle(mapOption.borderColor); + context.setFillStyle(hexToRgb(series[i].color, series[i].fillOpacity||mapOption.fillOpacity)); + if (mapOption.active == true && opts.tooltip) { + if (opts.tooltip.index == i) { + context.setStrokeStyle(mapOption.activeBorderColor); + context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity)); + } + } + var coorda = data[i].geometry.coordinates + for (var k = 0; k < coorda.length; k++) { + coords = coorda[k]; + if (coords.length == 1) { + coords = coords[0] + } + for (var j = 0; j < coords.length; j++) { + var gaosi = Array(2); + if (mapOption.mercator) { + gaosi = lonlat2mercator(coords[j][0], coords[j][1]) + } else { + gaosi = coords[j] + } + point = coordinateToPoint(gaosi[1], gaosi[0], bounds, scale, xoffset, yoffset) + if (j === 0) { + context.beginPath(); + context.moveTo(point.x, point.y); + } else { + context.lineTo(point.x, point.y); + } + } + context.fill(); + if (mapOption.border == true) { + context.stroke(); + } + } + } + if (opts.dataLabel == true) { + for (var i = 0; i < data.length; i++) { + var centerPoint = data[i].properties.centroid; + if (centerPoint) { + if (mapOption.mercator) { + centerPoint = lonlat2mercator(data[i].properties.centroid[0], data[i].properties.centroid[1]) + } + point = coordinateToPoint(centerPoint[1], centerPoint[0], bounds, scale, xoffset, yoffset); + let fontSize = data[i].textSize * opts.pix || config.fontSize; + let fontColor = data[i].textColor || opts.fontColor; + if(mapOption.active && mapOption.activeTextColor && opts.tooltip && opts.tooltip.index == i){ + fontColor = mapOption.activeTextColor; + } + let text = data[i].properties.name; + context.beginPath(); + context.setFontSize(fontSize) + context.setFillStyle(fontColor) + context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2); + context.closePath(); + context.stroke(); + } + } + } + opts.chartData.mapData = { + bounds: bounds, + scale: scale, + xoffset: xoffset, + yoffset: yoffset, + mercator: mapOption.mercator + } + drawToolTipBridge(opts, config, context, 1); + context.draw(); +} + +function normalInt(min, max, iter) { + iter = iter == 0 ? 1 : iter; + var arr = []; + for (var i = 0; i < iter; i++) { + arr[i] = Math.random(); + }; + return Math.floor(arr.reduce(function(i, j) { + return i + j + }) / iter * (max - min)) + min; +}; + +function collisionNew(area, points, width, height) { + var isIn = false; + for (let i = 0; i < points.length; i++) { + if (points[i].area) { + if (area[3] < points[i].area[1] || area[0] > points[i].area[2] || area[1] > points[i].area[3] || area[2] < points[i].area[0]) { + if (area[0] < 0 || area[1] < 0 || area[2] > width || area[3] > height) { + isIn = true; + break; + } else { + isIn = false; + } + } else { + isIn = true; + break; + } + } + } + return isIn; +}; + +function getWordCloudPoint(opts, type, context) { + let points = opts.series; + switch (type) { + case 'normal': + for (let i = 0; i < points.length; i++) { + let text = points[i].name; + let tHeight = points[i].textSize * opts.pix; + let tWidth = measureText(text, tHeight, context); + let x, y; + let area; + let breaknum = 0; + while (true) { + breaknum++; + x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2; + y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2; + area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 + + opts.height / 2 + ]; + let isCollision = collisionNew(area, points, opts.width, opts.height); + if (!isCollision) break; + if (breaknum == 1000) { + area = [-100, -100, -100, -100]; + break; + } + }; + points[i].area = area; + } + break; + case 'vertical': + function Spin() { + //获取均匀随机值,是否旋转,旋转的概率为(1-0.5) + if (Math.random() > 0.7) { + return true; + } else { + return false + }; + }; + for (let i = 0; i < points.length; i++) { + let text = points[i].name; + let tHeight = points[i].textSize * opts.pix; + let tWidth = measureText(text, tHeight, context); + let isSpin = Spin(); + let x, y, area, areav; + let breaknum = 0; + while (true) { + breaknum++; + let isCollision; + if (isSpin) { + x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2; + y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2; + area = [y - 5 - tWidth + opts.width / 2, (-x - 5 + opts.height / 2), y + 5 + opts.width / 2, (-x + tHeight + 5 + opts.height / 2)]; + areav = [opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) - 5, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) - 5, opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) + tHeight, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) + tWidth + 5]; + isCollision = collisionNew(areav, points, opts.height, opts.width); + } else { + x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2; + y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2; + area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 + opts.height / 2]; + isCollision = collisionNew(area, points, opts.width, opts.height); + } + if (!isCollision) break; + if (breaknum == 1000) { + area = [-1000, -1000, -1000, -1000]; + break; + } + }; + if (isSpin) { + points[i].area = areav; + points[i].areav = area; + } else { + points[i].area = area; + } + points[i].rotate = isSpin; + }; + break; + } + return points; +} + +function drawWordCloudDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let wordOption = assign({}, { + type: 'normal', + autoColors: true + }, opts.extra.word); + if (!opts.chartData.wordCloudData) { + opts.chartData.wordCloudData = getWordCloudPoint(opts, wordOption.type, context); + } + context.beginPath(); + context.setFillStyle(opts.background); + context.rect(0, 0, opts.width, opts.height); + context.fill(); + context.save(); + let points = opts.chartData.wordCloudData; + context.translate(opts.width / 2, opts.height / 2); + for (let i = 0; i < points.length; i++) { + context.save(); + if (points[i].rotate) { + context.rotate(90 * Math.PI / 180); + } + let text = points[i].name; + let tHeight = points[i].textSize * opts.pix; + let tWidth = measureText(text, tHeight, context); + context.beginPath(); + context.setStrokeStyle(points[i].color); + context.setFillStyle(points[i].color); + context.setFontSize(tHeight); + if (points[i].rotate) { + if (points[i].areav[0] > 0) { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.strokeText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process); + } else { + context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process); + } + } else { + context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process); + } + } + } else { + if (points[i].area[0] > 0) { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.strokeText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process); + } else { + context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process); + } + } else { + context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process); + } + } + } + context.stroke(); + context.restore(); + } + context.restore(); +} + +function drawFunnelDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let funnelOption = assign({}, { + type:'funnel', + activeWidth: 10, + activeOpacity: 0.3, + border: false, + borderWidth: 2, + borderColor: '#FFFFFF', + fillOpacity: 1, + minSize: 0, + labelAlign: 'right', + linearType: 'none', + customColor: [], + }, opts.extra.funnel); + let eachSpacing = (opts.height - opts.area[0] - opts.area[2]) / series.length; + let centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.height - opts.area[2] + }; + let activeWidth = funnelOption.activeWidth * opts.pix; + let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth); + let seriesNew = getFunnelDataPoints(series, radius, funnelOption, eachSpacing, process); + context.save(); + context.translate(centerPosition.x, centerPosition.y); + funnelOption.customColor = fillCustomColor(funnelOption.linearType, funnelOption.customColor, series, config); + if(funnelOption.type == 'pyramid'){ + for (let i = 0; i < seriesNew.length; i++) { + if (i == seriesNew.length -1) { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.beginPath(); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); + context.moveTo(-activeWidth, -eachSpacing); + context.lineTo(-seriesNew[i].radius - activeWidth, 0); + context.lineTo(seriesNew[i].radius + activeWidth, 0); + context.lineTo(activeWidth, -eachSpacing); + context.lineTo(-activeWidth, -eachSpacing); + context.closePath(); + context.fill(); + } + } + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i]; + context.beginPath(); + context.setLineWidth(funnelOption.borderWidth * opts.pix); + context.setStrokeStyle(funnelOption.borderColor); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); + if (funnelOption.linearType == 'custom') { + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + fillColor = grd + } + context.setFillStyle(fillColor); + context.moveTo(0, -eachSpacing); + context.lineTo(-seriesNew[i].radius, 0); + context.lineTo(seriesNew[i].radius, 0); + context.lineTo(0, -eachSpacing); + context.closePath(); + context.fill(); + if (funnelOption.border == true) { + context.stroke(); + } + } else { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.beginPath(); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); + context.moveTo(0, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, 0); + context.lineTo(-seriesNew[i + 1].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius + activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, 0); + context.lineTo(0, 0); + context.closePath(); + context.fill(); + } + } + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i]; + context.beginPath(); + context.setLineWidth(funnelOption.borderWidth * opts.pix); + context.setStrokeStyle(funnelOption.borderColor); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); + if (funnelOption.linearType == 'custom') { + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + fillColor = grd + } + context.setFillStyle(fillColor); + context.moveTo(0, 0); + context.lineTo(-seriesNew[i].radius, 0); + context.lineTo(-seriesNew[i + 1].radius, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, 0); + context.lineTo(0, 0); + context.closePath(); + context.fill(); + if (funnelOption.border == true) { + context.stroke(); + } + } + context.translate(0, -eachSpacing) + } + }else{ + context.translate(0, - (seriesNew.length - 1) * eachSpacing); + for (let i = 0; i < seriesNew.length; i++) { + if (i == seriesNew.length - 1) { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.beginPath(); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); + context.moveTo(-activeWidth - funnelOption.minSize/2, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing); + context.lineTo(activeWidth + funnelOption.minSize/2, 0); + context.lineTo(-activeWidth - funnelOption.minSize/2, 0); + context.closePath(); + context.fill(); + } + } + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing, centerPosition.x + seriesNew[i].radius, centerPosition.y ]; + context.beginPath(); + context.setLineWidth(funnelOption.borderWidth * opts.pix); + context.setStrokeStyle(funnelOption.borderColor); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); + if (funnelOption.linearType == 'custom') { + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + fillColor = grd + } + context.setFillStyle(fillColor); + context.moveTo(0, 0); + context.lineTo(-funnelOption.minSize/2, 0); + context.lineTo(-seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, -eachSpacing); + context.lineTo(funnelOption.minSize/2, 0); + context.lineTo(0, 0); + context.closePath(); + context.fill(); + if (funnelOption.border == true) { + context.stroke(); + } + } else { + if (opts.tooltip) { + if (opts.tooltip.index == i) { + context.beginPath(); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); + context.moveTo(0, 0); + context.lineTo(-seriesNew[i + 1].radius - activeWidth, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius + activeWidth, 0); + context.lineTo(0, 0); + context.closePath(); + context.fill(); + } + } + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i - 1)]; + context.beginPath(); + context.setLineWidth(funnelOption.borderWidth * opts.pix); + context.setStrokeStyle(funnelOption.borderColor); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); + if (funnelOption.linearType == 'custom') { + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + fillColor = grd + } + context.setFillStyle(fillColor); + context.moveTo(0, 0); + context.lineTo(-seriesNew[i + 1].radius, 0); + context.lineTo(-seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius, 0); + context.lineTo(0, 0); + context.closePath(); + context.fill(); + if (funnelOption.border == true) { + context.stroke(); + } + } + context.translate(0, eachSpacing) + } + } + + context.restore(); + if (opts.dataLabel !== false && process === 1) { + drawFunnelText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition); + } + if (process === 1) { + drawFunnelCenterText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition); + } + return { + center: centerPosition, + radius: radius, + series: seriesNew + }; +} + +function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) { + for (let i = 0; i < series.length; i++) { + let item = series[i]; + if(item.labelShow === false){ + continue; + } + let startX, endX, startY, fontSize; + let text = item.formatter ? item.formatter(item,i,series,opts) : util.toFixed(item._proportion_ * 100) + '%'; + text = item.labelText ? item.labelText : text; + if (labelAlign == 'right') { + if (i == series.length -1) { + startX = (item.funnelArea[2] + centerPosition.x) / 2; + } else { + startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2; + } + endX = startX + activeWidth * 2; + startY = item.funnelArea[1] + eachSpacing / 2; + fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix; + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(item.color); + context.setFillStyle(item.color); + context.beginPath(); + context.moveTo(startX, startY); + context.lineTo(endX, startY); + context.stroke(); + context.closePath(); + context.beginPath(); + context.moveTo(endX, startY); + context.arc(endX, startY, 2 * opts.pix, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.textColor || opts.fontColor); + context.fillText(text, endX + 5, startY + fontSize / 2 - 2); + context.closePath(); + context.stroke(); + context.closePath(); + } + if (labelAlign == 'left') { + if (i == series.length -1) { + startX = (item.funnelArea[0] + centerPosition.x) / 2; + } else { + startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2; + } + endX = startX - activeWidth * 2; + startY = item.funnelArea[1] + eachSpacing / 2; + fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix; + context.setLineWidth(1 * opts.pix); + context.setStrokeStyle(item.color); + context.setFillStyle(item.color); + context.beginPath(); + context.moveTo(startX, startY); + context.lineTo(endX, startY); + context.stroke(); + context.closePath(); + context.beginPath(); + context.moveTo(endX, startY); + context.arc(endX, startY, 2, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.textColor || opts.fontColor); + context.fillText(text, endX - 5 - measureText(text, fontSize, context), startY + fontSize / 2 - 2); + context.closePath(); + context.stroke(); + context.closePath(); + } + } +} + +function drawFunnelCenterText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) { + for (let i = 0; i < series.length; i++) { + let item = series[i]; + let startY, fontSize; + if (item.centerText) { + startY = item.funnelArea[1] + eachSpacing / 2; + fontSize = item.centerTextSize * opts.pix || opts.fontSize * opts.pix; + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.centerTextColor || "#FFFFFF"); + context.fillText(item.centerText, centerPosition.x - measureText(item.centerText, fontSize, context) / 2, startY + fontSize / 2 - 2); + context.closePath(); + context.stroke(); + context.closePath(); + } + } +} + + +function drawCanvas(opts, context) { + context.save(); + context.translate(0, 0.5); + context.restore(); + context.draw(); +} + +var Timing = { + easeIn: function easeIn(pos) { + return Math.pow(pos, 3); + }, + easeOut: function easeOut(pos) { + return Math.pow(pos - 1, 3) + 1; + }, + easeInOut: function easeInOut(pos) { + if ((pos /= 0.5) < 1) { + return 0.5 * Math.pow(pos, 3); + } else { + return 0.5 * (Math.pow(pos - 2, 3) + 2); + } + }, + linear: function linear(pos) { + return pos; + } +}; + +function Animation(opts) { + this.isStop = false; + opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration; + opts.timing = opts.timing || 'easeInOut'; + var delay = 17; + function createAnimationFrame() { + if (typeof setTimeout !== 'undefined') { + return function(step, delay) { + setTimeout(function() { + var timeStamp = +new Date(); + step(timeStamp); + }, delay); + }; + } else if (typeof requestAnimationFrame !== 'undefined') { + return requestAnimationFrame; + } else { + return function(step) { + step(null); + }; + } + }; + var animationFrame = createAnimationFrame(); + var startTimeStamp = null; + var _step = function step(timestamp) { + if (timestamp === null || this.isStop === true) { + opts.onProcess && opts.onProcess(1); + opts.onAnimationFinish && opts.onAnimationFinish(); + return; + } + if (startTimeStamp === null) { + startTimeStamp = timestamp; + } + if (timestamp - startTimeStamp < opts.duration) { + var process = (timestamp - startTimeStamp) / opts.duration; + var timingFunction = Timing[opts.timing]; + process = timingFunction(process); + opts.onProcess && opts.onProcess(process); + animationFrame(_step, delay); + } else { + opts.onProcess && opts.onProcess(1); + opts.onAnimationFinish && opts.onAnimationFinish(); + } + }; + _step = _step.bind(this); + animationFrame(_step, delay); +} + +Animation.prototype.stop = function() { + this.isStop = true; +}; + +function drawCharts(type, opts, config, context) { + var _this = this; + var series = opts.series; + //兼容ECharts饼图类数据格式 + if (type === 'pie' || type === 'ring' || type === 'mount' || type === 'rose' || type === 'funnel') { + series = fixPieSeries(series, opts, config); + } + var categories = opts.categories; + if (type === 'mount') { + categories = []; + for (let j = 0; j < series.length; j++) { + if(series[j].show !== false) categories.push(series[j].name) + } + opts.categories = categories; + } + series = fillSeries(series, opts, config); + var duration = opts.animation ? opts.duration : 0; + _this.animationInstance && _this.animationInstance.stop(); + var seriesMA = null; + if (type == 'candle') { + let average = assign({}, opts.extra.candle.average); + if (average.show) { + seriesMA = calCandleMA(average.day, average.name, average.color, series[0].data); + seriesMA = fillSeries(seriesMA, opts, config); + opts.seriesMA = seriesMA; + } else if (opts.seriesMA) { + seriesMA = opts.seriesMA = fillSeries(opts.seriesMA, opts, config); + } else { + seriesMA = series; + } + } else { + seriesMA = series; + } + /* 过滤掉show=false的series */ + opts._series_ = series = filterSeries(series); + //重新计算图表区域 + opts.area = new Array(4); + //复位绘图区域 + for (let j = 0; j < 4; j++) { + opts.area[j] = opts.padding[j] * opts.pix; + } + //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域 + var _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData, context), + legendHeight = _calLegendData.area.wholeHeight, + legendWidth = _calLegendData.area.wholeWidth; + + switch (opts.legend.position) { + case 'top': + opts.area[0] += legendHeight; + break; + case 'bottom': + opts.area[2] += legendHeight; + break; + case 'left': + opts.area[3] += legendWidth; + break; + case 'right': + opts.area[1] += legendWidth; + break; + } + + let _calYAxisData = {}, + yAxisWidth = 0; + if (opts.type === 'line' || opts.type === 'column'|| opts.type === 'mount' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') { + _calYAxisData = calYAxisData(series, opts, config, context); + yAxisWidth = _calYAxisData.yAxisWidth; + //如果显示Y轴标题 + if (opts.yAxis.showTitle) { + let maxTitleHeight = 0; + for (let i = 0; i < opts.yAxis.data.length; i++) { + maxTitleHeight = Math.max(maxTitleHeight, opts.yAxis.data[i].titleFontSize ? opts.yAxis.data[i].titleFontSize * opts.pix : config.fontSize) + } + opts.area[0] += maxTitleHeight; + } + let rightIndex = 0, + leftIndex = 0; + //计算主绘图区域左右位置 + for (let i = 0; i < yAxisWidth.length; i++) { + if (yAxisWidth[i].position == 'left') { + if (leftIndex > 0) { + opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix; + } else { + opts.area[3] += yAxisWidth[i].width; + } + leftIndex += 1; + } else if (yAxisWidth[i].position == 'right') { + if (rightIndex > 0) { + opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix; + } else { + opts.area[1] += yAxisWidth[i].width; + } + rightIndex += 1; + } + } + } else { + config.yAxisWidth = yAxisWidth; + } + opts.chartData.yAxisData = _calYAxisData; + + if (opts.categories && opts.categories.length && opts.type !== 'radar' && opts.type !== 'gauge' && opts.type !== 'bar') { + opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config); + let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing, context), + xAxisHeight = _calCategoriesData.xAxisHeight, + angle = _calCategoriesData.angle; + config.xAxisHeight = xAxisHeight; + config._xAxisTextAngle_ = angle; + opts.area[2] += xAxisHeight; + opts.chartData.categoriesData = _calCategoriesData; + } else { + if (opts.type === 'line' || opts.type === 'area' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') { + opts.chartData.xAxisData = calXAxisData(series, opts, config, context); + categories = opts.chartData.xAxisData.rangesFormat; + let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing, context), + xAxisHeight = _calCategoriesData.xAxisHeight, + angle = _calCategoriesData.angle; + config.xAxisHeight = xAxisHeight; + config._xAxisTextAngle_ = angle; + opts.area[2] += xAxisHeight; + opts.chartData.categoriesData = _calCategoriesData; + } else { + opts.chartData.xAxisData = { + xAxisPoints: [] + }; + } + } + + //计算右对齐偏移距离 + if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) { + let offsetLeft = 0, + xAxisPoints = opts.chartData.xAxisData.xAxisPoints, + startX = opts.chartData.xAxisData.startX, + endX = opts.chartData.xAxisData.endX, + eachSpacing = opts.chartData.xAxisData.eachSpacing; + let totalWidth = eachSpacing * (xAxisPoints.length - 1); + let screenWidth = endX - startX; + offsetLeft = screenWidth - totalWidth; + _this.scrollOption.currentOffset = offsetLeft; + _this.scrollOption.startTouchX = offsetLeft; + _this.scrollOption.distance = 0; + _this.scrollOption.lastMoveTime = 0; + opts._scrollDistance_ = offsetLeft; + } + + if (type === 'pie' || type === 'ring' || type === 'rose') { + config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA, config, context, opts); + } + + switch (type) { + case 'word': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawWordCloudDataPoints(series, opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'map': + context.clearRect(0, 0, opts.width, opts.height); + drawMapDataPoints(series, opts, config, context); + setTimeout(()=>{ + this.uevent.trigger('renderComplete'); + },50) + break; + case 'funnel': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.funnelData = drawFunnelDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'line': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process), + xAxisPoints = _drawLineDataPoints.xAxisPoints, + calPoints = _drawLineDataPoints.calPoints, + eachSpacing = _drawLineDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'scatter': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawScatterDataPoints = drawScatterDataPoints(series, opts, config, context, process), + xAxisPoints = _drawScatterDataPoints.xAxisPoints, + calPoints = _drawScatterDataPoints.calPoints, + eachSpacing = _drawScatterDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'bubble': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawBubbleDataPoints = drawBubbleDataPoints(series, opts, config, context, process), + xAxisPoints = _drawBubbleDataPoints.xAxisPoints, + calPoints = _drawBubbleDataPoints.calPoints, + eachSpacing = _drawBubbleDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'mix': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process), + xAxisPoints = _drawMixDataPoints.xAxisPoints, + calPoints = _drawMixDataPoints.calPoints, + eachSpacing = _drawMixDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'column': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process), + xAxisPoints = _drawColumnDataPoints.xAxisPoints, + calPoints = _drawColumnDataPoints.calPoints, + eachSpacing = _drawColumnDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'mount': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawMountDataPoints = drawMountDataPoints(series, opts, config, context, process), + xAxisPoints = _drawMountDataPoints.xAxisPoints, + calPoints = _drawMountDataPoints.calPoints, + eachSpacing = _drawMountDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'bar': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawXAxis(categories, opts, config, context); + var _drawBarDataPoints = drawBarDataPoints(series, opts, config, context, process), + yAxisPoints = _drawBarDataPoints.yAxisPoints, + calPoints = _drawBarDataPoints.calPoints, + eachSpacing = _drawBarDataPoints.eachSpacing; + opts.chartData.yAxisPoints = yAxisPoints; + opts.chartData.xAxisPoints = opts.chartData.xAxisData.xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, yAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'area': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process), + xAxisPoints = _drawAreaDataPoints.xAxisPoints, + calPoints = _drawAreaDataPoints.calPoints, + eachSpacing = _drawAreaDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'ring': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'pie': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'rose': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'radar': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'arcbar': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'gauge': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + case 'candle': + this.animationInstance = new Animation({ + timing: opts.timing, + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process), + xAxisPoints = _drawCandleDataPoints.xAxisPoints, + calPoints = _drawCandleDataPoints.calPoints, + eachSpacing = _drawCandleDataPoints.eachSpacing; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(opts, config, context); + } + if (seriesMA) { + drawLegend(seriesMA, opts, config, context, opts.chartData); + } else { + drawLegend(opts.series, opts, config, context, opts.chartData); + } + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.uevent.trigger('renderComplete'); + } + }); + break; + } +} + +function uChartsEvent() { + this.events = {}; +} + +uChartsEvent.prototype.addEventListener = function(type, listener) { + this.events[type] = this.events[type] || []; + this.events[type].push(listener); +}; + +uChartsEvent.prototype.delEventListener = function(type) { + this.events[type] = []; +}; + +uChartsEvent.prototype.trigger = function() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + var type = args[0]; + var params = args.slice(1); + if (!!this.events[type]) { + this.events[type].forEach(function(listener) { + try { + listener.apply(null, params); + } catch (e) { + //console.log('[uCharts] '+e); + } + }); + } +}; + +var uCharts = function uCharts(opts) { + opts.pix = opts.pixelRatio ? opts.pixelRatio : 1; + opts.fontSize = opts.fontSize ? opts.fontSize : 13; + opts.fontColor = opts.fontColor ? opts.fontColor : config.fontColor; + if (opts.background == "" || opts.background == "none") { + opts.background = "#FFFFFF" + } + opts.title = assign({}, opts.title); + opts.subtitle = assign({}, opts.subtitle); + opts.duration = opts.duration ? opts.duration : 1000; + opts.yAxis = assign({}, { + data: [], + showTitle: false, + disabled: false, + disableGrid: false, + gridSet: 'number', + splitNumber: 5, + gridType: 'solid', + dashLength: 4 * opts.pix, + gridColor: '#cccccc', + padding: 10, + fontColor: '#666666' + }, opts.yAxis); + opts.xAxis = assign({}, { + rotateLabel: false, + rotateAngle:45, + disabled: false, + disableGrid: false, + splitNumber: 5, + calibration:false, + fontColor: '#666666', + fontSize: 13, + lineHeight: 20, + marginTop: 0, + gridType: 'solid', + dashLength: 4, + scrollAlign: 'left', + boundaryGap: 'center', + axisLine: true, + axisLineColor: '#cccccc', + titleFontSize: 13, + titleOffsetY: 0, + titleOffsetX: 0, + titleFontColor: '#666666' + }, opts.xAxis); + opts.xAxis.scrollPosition = opts.xAxis.scrollAlign; + opts.legend = assign({}, { + show: true, + position: 'bottom', + float: 'center', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: 'rgba(0,0,0,0)', + borderWidth: 0, + padding: 5, + margin: 5, + itemGap: 10, + fontSize: opts.fontSize, + lineHeight: opts.fontSize, + fontColor: opts.fontColor, + formatter: {}, + hiddenColor: '#CECECE' + }, opts.legend); + opts.extra = assign({ + tooltip:{ + legendShape: 'auto' + } + }, opts.extra); + opts.rotate = opts.rotate ? true : false; + opts.animation = opts.animation ? true : false; + opts.rotate = opts.rotate ? true : false; + opts.canvas2d = opts.canvas2d ? true : false; + + let config$$1 = assign({}, config); + config$$1.color = opts.color ? opts.color : config$$1.color; + if (opts.type == 'pie') { + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix; + } + if (opts.type == 'ring') { + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.ring.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix; + } + if (opts.type == 'rose') { + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix; + } + config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pix; + + //屏幕旋转 + config$$1.rotate = opts.rotate; + if (opts.rotate) { + let tempWidth = opts.width; + let tempHeight = opts.height; + opts.width = tempHeight; + opts.height = tempWidth; + } + + //适配高分屏 + opts.padding = opts.padding ? opts.padding : config$$1.padding; + config$$1.yAxisWidth = config.yAxisWidth * opts.pix; + config$$1.fontSize = opts.fontSize * opts.pix; + config$$1.titleFontSize = config.titleFontSize * opts.pix; + config$$1.subtitleFontSize = config.subtitleFontSize * opts.pix; + if(!opts.context){ + throw new Error('[uCharts] 未获取到context!注意:v2.0版本后,需要自行获取canvas的绘图上下文并传入opts.context!'); + } + this.context = opts.context; + if (!this.context.setTextAlign) { + this.context.setStrokeStyle = function(e) { + return this.strokeStyle = e; + } + this.context.setLineWidth = function(e) { + return this.lineWidth = e; + } + this.context.setLineCap = function(e) { + return this.lineCap = e; + } + this.context.setFontSize = function(e) { + return this.font = e + "px sans-serif"; + } + this.context.setFillStyle = function(e) { + return this.fillStyle = e; + } + this.context.setTextAlign = function(e) { + return this.textAlign = e; + } + this.context.setTextBaseline = function(e) { + return this.textBaseline = e; + } + this.context.setShadow = function(offsetX,offsetY,blur,color) { + this.shadowColor = color; + this.shadowOffsetX = offsetX; + this.shadowOffsetY = offsetY; + this.shadowBlur = blur; + } + this.context.draw = function() {} + } + //兼容NVUEsetLineDash + if(!this.context.setLineDash){ + this.context.setLineDash = function(e) {} + } + opts.chartData = {}; + this.uevent = new uChartsEvent(); + this.scrollOption = { + currentOffset: 0, + startTouchX: 0, + distance: 0, + lastMoveTime: 0 + }; + this.opts = opts; + this.config = config$$1; + drawCharts.call(this, opts.type, opts, config$$1, this.context); +}; + +uCharts.prototype.updateData = function() { + let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.opts = assign({}, this.opts, data); + this.opts.updateData = true; + let scrollPosition = data.scrollPosition || 'current'; + switch (scrollPosition) { + case 'current': + this.opts._scrollDistance_ = this.scrollOption.currentOffset; + break; + case 'left': + this.opts._scrollDistance_ = 0; + this.scrollOption = { + currentOffset: 0, + startTouchX: 0, + distance: 0, + lastMoveTime: 0 + }; + break; + case 'right': + let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context), yAxisWidth = _calYAxisData.yAxisWidth; + this.config.yAxisWidth = yAxisWidth; + let offsetLeft = 0; + let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; + let totalWidth = eachSpacing * (xAxisPoints.length - 1); + let screenWidth = endX - startX; + offsetLeft = screenWidth - totalWidth; + this.scrollOption = { + currentOffset: offsetLeft, + startTouchX: offsetLeft, + distance: 0, + lastMoveTime: 0 + }; + this.opts._scrollDistance_ = offsetLeft; + break; + } + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); +}; + +uCharts.prototype.zoom = function() { + var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount; + if (this.opts.enableScroll !== true) { + console.log('[uCharts] 请启用滚动条后使用') + return; + } + //当前屏幕中间点 + let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(this.opts.xAxis.itemCount / 2); + this.opts.animation = false; + this.opts.xAxis.itemCount = val.itemCount; + //重新计算x轴偏移距离 + let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context), + yAxisWidth = _calYAxisData.yAxisWidth; + this.config.yAxisWidth = yAxisWidth; + let offsetLeft = 0; + let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; + let centerLeft = eachSpacing * centerPoint; + let screenWidth = endX - startX; + let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1); + offsetLeft = screenWidth / 2 - centerLeft; + if (offsetLeft > 0) { + offsetLeft = 0; + } + if (offsetLeft < MaxLeft) { + offsetLeft = MaxLeft; + } + this.scrollOption = { + currentOffset: offsetLeft, + startTouchX: 0, + distance: 0, + lastMoveTime: 0 + }; + calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts); + this.opts._scrollDistance_ = offsetLeft; + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); +}; + +uCharts.prototype.dobuleZoom = function(e) { + if (this.opts.enableScroll !== true) { + console.log('[uCharts] 请启用滚动条后使用') + return; + } + const tcs = e.changedTouches; + if (tcs.length < 2) { + return; + } + for (var i = 0; i < tcs.length; i++) { + tcs[i].x = tcs[i].x ? tcs[i].x : tcs[i].clientX; + tcs[i].y = tcs[i].y ? tcs[i].y : tcs[i].clientY; + } + const ntcs = [getTouches(tcs[0], this.opts, e),getTouches(tcs[1], this.opts, e)]; + const xlength = Math.abs(ntcs[0].x - ntcs[1].x); + // 记录初始的两指之间的数据 + if(!this.scrollOption.moveCount){ + let cts0 = {changedTouches:[{x:tcs[0].x,y:this.opts.area[0] / this.opts.pix + 2}]}; + let cts1 = {changedTouches:[{x:tcs[1].x,y:this.opts.area[0] / this.opts.pix + 2}]}; + if(this.opts.rotate){ + cts0 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[0].y}]}; + cts1 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[1].y}]}; + } + const moveCurrent1 = this.getCurrentDataIndex(cts0).index; + const moveCurrent2 = this.getCurrentDataIndex(cts1).index; + const moveCount = Math.abs(moveCurrent1 - moveCurrent2); + this.scrollOption.moveCount = moveCount; + this.scrollOption.moveCurrent1 = Math.min(moveCurrent1, moveCurrent2); + this.scrollOption.moveCurrent2 = Math.max(moveCurrent1, moveCurrent2); + return; + } + + let currentEachSpacing = xlength / this.scrollOption.moveCount; + let itemCount = (this.opts.width - this.opts.area[1] - this.opts.area[3]) / currentEachSpacing; + itemCount = itemCount <= 2 ? 2 : itemCount; + itemCount = itemCount >= this.opts.categories.length ? this.opts.categories.length : itemCount; + this.opts.animation = false; + this.opts.xAxis.itemCount = itemCount; + // 重新计算滚动条偏移距离 + let offsetLeft = 0; + let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; + let currentLeft = eachSpacing * this.scrollOption.moveCurrent1; + let screenWidth = endX - startX; + let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1); + offsetLeft = -currentLeft+Math.min(ntcs[0].x,ntcs[1].x)-this.opts.area[3]-eachSpacing; + if (offsetLeft > 0) { + offsetLeft = 0; + } + if (offsetLeft < MaxLeft) { + offsetLeft = MaxLeft; + } + this.scrollOption.currentOffset= offsetLeft; + this.scrollOption.startTouchX= 0; + this.scrollOption.distance=0; + calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts); + this.opts._scrollDistance_ = offsetLeft; + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); +} + +uCharts.prototype.stopAnimation = function() { + this.animationInstance && this.animationInstance.stop(); +}; + +uCharts.prototype.addEventListener = function(type, listener) { + this.uevent.addEventListener(type, listener); +}; + +uCharts.prototype.delEventListener = function(type) { + this.uevent.delEventListener(type); +}; + +uCharts.prototype.getCurrentDataIndex = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + let _touches$ = getTouches(touches, this.opts, e); + if (this.opts.type === 'pie' || this.opts.type === 'ring') { + return findPieChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.pieData, this.opts); + } else if (this.opts.type === 'rose') { + return findRoseChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.pieData, this.opts); + } else if (this.opts.type === 'radar') { + return findRadarChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.radarData, this.opts.categories.length); + } else if (this.opts.type === 'funnel') { + return findFunnelChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.funnelData); + } else if (this.opts.type === 'map') { + return findMapChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts); + } else if (this.opts.type === 'word') { + return findWordChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.wordCloudData); + } else if (this.opts.type === 'bar') { + return findBarChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset)); + } else { + return findCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset)); + } + } + return -1; +}; + +uCharts.prototype.getLegendDataIndex = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + let _touches$ = getTouches(touches, this.opts, e); + return findLegendIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.legendData); + } + return -1; +}; + +uCharts.prototype.touchLegend = function(e) { + var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + var _touches$ = getTouches(touches, this.opts, e); + var index = this.getLegendDataIndex(e); + if (index >= 0) { + if (this.opts.type == 'candle') { + this.opts.seriesMA[index].show = !this.opts.seriesMA[index].show; + } else { + this.opts.series[index].show = !this.opts.series[index].show; + } + this.opts.animation = option.animation ? true : false; + this.opts._scrollDistance_ = this.scrollOption.currentOffset; + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); + } + } + +}; + +uCharts.prototype.showToolTip = function(e) { + var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (!touches) { + console.log("[uCharts] 未获取到event坐标信息"); + } + var _touches$ = getTouches(touches, this.opts, e); + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column' || this.opts.type === 'scatter' || this.opts.type === 'bubble') { + var current = this.getCurrentDataIndex(e); + var index = option.index == undefined ? current.index : option.index; + if (index > -1 || index.length>0) { + var seriesData = getSeriesDataItem(this.opts.series, index, current.group); + if (seriesData.length !== 0) { + var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option), + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: option.textList !== undefined ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index, + group: current.group + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'mount') { + var index = option.index == undefined ? this.getCurrentDataIndex(e).index : option.index; + if (index > -1) { + var opts = assign({}, this.opts, {animation: false}); + var seriesData = assign({}, opts._series_[index]); + var textList = [{ + text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data, + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape + }]; + var offset = { + x: opts.chartData.calPoints[index].x, + y: _touches$.y + }; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'bar') { + var current = this.getCurrentDataIndex(e); + var index = option.index == undefined ? current.index : option.index; + if (index > -1 || index.length>0) { + var seriesData = getSeriesDataItem(this.opts.series, index, current.group); + if (seriesData.length !== 0) { + var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option), + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; + offset.x = _touches$.x; + opts.tooltip = { + textList: option.textList !== undefined ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'mix') { + var current = this.getCurrentDataIndex(e); + var index = option.index == undefined ? current.index : option.index; + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var _getMixToolTipData = getMixToolTipData(seriesData, this.opts, index, this.opts.categories, option), + textList = _getMixToolTipData.textList, + offset = _getMixToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'candle') { + var current = this.getCurrentDataIndex(e); + var index = option.index == undefined ? current.index : option.index; + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts, index, this.opts.categories, this.opts.extra.candle, option), + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose' || this.opts.type === 'funnel') { + var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index; + if (index > -1) { + var opts = assign({}, this.opts, {animation: false}); + var seriesData = assign({}, opts._series_[index]); + var textList = [{ + text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data, + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape + }]; + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'map') { + var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index; + if (index > -1) { + var opts = assign({}, this.opts, {animation: false}); + var seriesData = assign({}, this.opts.series[index]); + seriesData.name = seriesData.properties.name + var textList = [{ + text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name, + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape + }]; + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + opts.updateData = false; + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'word') { + var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index; + if (index > -1) { + var opts = assign({}, this.opts, {animation: false}); + var seriesData = assign({}, this.opts.series[index]); + var textList = [{ + text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name, + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape + }]; + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + opts.updateData = false; + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'radar') { + var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index; + if (index > -1) { + var opts = assign({}, this.opts, {animation: false}); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var textList = seriesData.map((item) => { + return { + text: option.formatter ? option.formatter(item, this.opts.categories[index], index, this.opts) : item.name + ': ' + item.data, + color: item.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? item.legendShape : this.opts.extra.tooltip.legendShape + }; + }); + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: option.textList ? option.textList : textList, + offset: option.offset !== undefined ? option.offset : offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } +}; + +uCharts.prototype.translate = function(distance) { + this.scrollOption = { + currentOffset: distance, + startTouchX: distance, + distance: 0, + lastMoveTime: 0 + }; + let opts = assign({}, this.opts, { + _scrollDistance_: distance, + animation: false + }); + drawCharts.call(this, this.opts.type, opts, this.config, this.context); +}; + +uCharts.prototype.scrollStart = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + var _touches$ = getTouches(touches, this.opts, e); + if (touches && this.opts.enableScroll === true) { + this.scrollOption.startTouchX = _touches$.x; + } +}; + +uCharts.prototype.scroll = function(e) { + if (this.scrollOption.lastMoveTime === 0) { + this.scrollOption.lastMoveTime = Date.now(); + } + let Limit = this.opts.touchMoveLimit || 60; + let currMoveTime = Date.now(); + let duration = currMoveTime - this.scrollOption.lastMoveTime; + if (duration < Math.floor(1000 / Limit)) return; + if (this.scrollOption.startTouchX == 0) return; + this.scrollOption.lastMoveTime = currMoveTime; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches && this.opts.enableScroll === true) { + var _touches$ = getTouches(touches, this.opts, e); + var _distance; + _distance = _touches$.x - this.scrollOption.startTouchX; + var currentOffset = this.scrollOption.currentOffset; + var validDistance = calValidDistance(this, currentOffset + _distance, this.opts.chartData, this.config, this.opts); + this.scrollOption.distance = _distance = validDistance - currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset + _distance, + animation: false + }); + this.opts = opts; + drawCharts.call(this, opts.type, opts, this.config, this.context); + return currentOffset + _distance; + } +}; + +uCharts.prototype.scrollEnd = function(e) { + if (this.opts.enableScroll === true) { + var _scrollOption = this.scrollOption, + currentOffset = _scrollOption.currentOffset, + distance = _scrollOption.distance; + this.scrollOption.currentOffset = currentOffset + distance; + this.scrollOption.distance = 0; + this.scrollOption.moveCount = 0; + } +}; + +export default uCharts; \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js new file mode 100644 index 00000000..0902ecd3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js @@ -0,0 +1,18 @@ +/* + * uCharts (R) + * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台 + * Copyright (C) 2021 QIUN (R) 秋云 https://www.ucharts.cn All rights reserved. + * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) + * 复制使用请保留本段注释,感谢支持开源! + * + * uCharts (R) 官方网站 + * https://www.uCharts.cn + * + * 开源地址: + * https://gitee.com/uCharts/uCharts + * + * uni-app插件市场地址: + * http://ext.dcloud.net.cn/plugin?id=271 + * + */ +"use strict";var config={version:"v2.5.0-20230101",yAxisWidth:15,xAxisHeight:22,padding:[10,10,10,10],rotate:false,fontSize:13,fontColor:"#666666",dataPointShape:["circle","circle","circle","circle"],color:["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],linearColor:["#0EE2F8","#2BDCA8","#FA7D8D","#EB88E2","#2AE3A0","#0EE2F8","#EB88E2","#6773E3","#F78A85"],pieChartLinePadding:15,pieChartTextPadding:5,titleFontSize:20,subtitleFontSize:15,radarLabelTextMargin:13};var assign=function(e,...t){if(e==null){throw new TypeError("[uCharts] Cannot convert undefined or null to object")}if(!t||t.length<=0){return e}function i(e,a){for(let t in a){e[t]=e[t]&&e[t].toString()==="[object Object]"?i(e[t],a[t]):e[t]=a[t]}return e}t.forEach(t=>{e=i(e,t)});return e};var util={toFixed:function t(e,a){a=a||2;if(this.isFloat(e)){e=e.toFixed(a)}return e},isFloat:function t(e){return e%1!==0},approximatelyEqual:function t(e,a){return Math.abs(e-a)<1e-10},isSameSign:function t(e,a){return Math.abs(e)===e&&Math.abs(a)===a||Math.abs(e)!==e&&Math.abs(a)!==a},isSameXCoordinateArea:function t(e,a){return this.isSameSign(e.x,a.x)},isCollision:function t(e,a){e.end={};e.end.x=e.start.x+e.width;e.end.y=e.start.y-e.height;a.end={};a.end.x=a.start.x+a.width;a.end.y=a.start.y-a.height;var i=a.start.x>e.end.x||a.end.xe.start.y||a.start.y1){if(r.extra.mount.widthRatio>2)r.extra.mount.widthRatio=2;n+=(r.extra.mount.widthRatio-1)*a.eachSpacing}var l=e;if(e>=0){l=0;t.uevent.trigger("scrollLeft");t.scrollOption.position="left";r.xAxis.scrollPosition="left"}else if(Math.abs(e)>=n-o){l=o-n;t.uevent.trigger("scrollRight");t.scrollOption.position="right";r.xAxis.scrollPosition="right"}else{t.scrollOption.position=e;r.xAxis.scrollPosition=e}return l}function isInAngleRange(t,e,a){function i(t){while(t<0){t+=2*Math.PI}while(t>2*Math.PI){t-=2*Math.PI}return t}t=i(t);e=i(e);a=i(a);if(e>a){a+=2*Math.PI;if(t=e&&t<=a}function createCurveControlPoints(t,e){function a(t,e){if(t[e-1]&&t[e+1]){return t[e].y>=Math.max(t[e-1].y,t[e+1].y)||t[e].y<=Math.min(t[e-1].y,t[e+1].y)}else{return false}}function c(t,e){if(t[e-1]&&t[e+1]){return t[e].x>=Math.max(t[e-1].x,t[e+1].x)||t[e].x<=Math.min(t[e-1].x,t[e+1].x)}else{return false}}var i=.2;var r=.2;var o=null;var n=null;var l=null;var s=null;if(e<1){o=t[0].x+(t[1].x-t[0].x)*i;n=t[0].y+(t[1].y-t[0].y)*i}else{o=t[e].x+(t[e+1].x-t[e-1].x)*i;n=t[e].y+(t[e+1].y-t[e-1].y)*i}if(e>t.length-3){var h=t.length-1;l=t[h].x-(t[h].x-t[h-1].x)*r;s=t[h].y-(t[h].y-t[h-1].y)*r}else{l=t[e+1].x-(t[e+2].x-t[e].x)*r;s=t[e+1].y-(t[e+2].y-t[e].y)*r}if(a(t,e+1)){s=t[e+1].y}if(a(t,e)){n=t[e].y}if(c(t,e+1)){l=t[e+1].x}if(c(t,e)){o=t[e].x}if(n>=Math.max(t[e].y,t[e+1].y)||n<=Math.min(t[e].y,t[e+1].y)){n=t[e].y}if(s>=Math.max(t[e].y,t[e+1].y)||s<=Math.min(t[e].y,t[e+1].y)){s=t[e+1].y}if(o>=Math.max(t[e].x,t[e+1].x)||o<=Math.min(t[e].x,t[e+1].x)){o=t[e].x}if(l>=Math.max(t[e].x,t[e+1].x)||l<=Math.min(t[e].x,t[e+1].x)){l=t[e+1].x}return{ctrA:{x:o,y:n},ctrB:{x:l,y:s}}}function convertCoordinateOrigin(t,e,a){return{x:a.x+t,y:a.y-e}}function avoidCollision(t,e){if(e){while(util.isCollision(t,e)){if(t.start.x>0){t.start.y--}else if(t.start.x<0){t.start.y++}else{if(t.start.y>0){t.start.y++}else{t.start.y--}}}}return t}function fixPieSeries(e,a,t){let i=[];if(e.length>0&&e[0].data.constructor.toString().indexOf("Array")>-1){a._pieSeries_=e;let t=e[0].data;for(var r=0;r=1e4){a=1e3}else if(i>=1e3){a=100}else if(i>=100){a=10}else if(i>=10){a=5}else if(i>=1){a=1}else if(i>=.1){a=.1}else if(i>=.01){a=.01}else if(i>=.001){a=.001}else if(i>=1e-4){a=1e-4}else if(i>=1e-5){a=1e-5}else{a=1e-6}return{minRange:findRange(t,"lower",a),maxRange:findRange(e,"upper",a)}}function measureText(a,t,e){var i=0;a=String(a);e=false;if(e!==false&&e!==undefined&&e.setFontSize&&e.measureText){e.setFontSize(t);return e.measureText(a).width}else{var a=a.split("");for(let e=0;e-1;if(n){let t=filterSeries(e);for(var l=0;l5&&arguments[5]!==undefined?arguments[5]:{};var l=a.chartData.calPoints?a.chartData.calPoints:[];let s={};if(r.length>0){let e=[];for(let t=0;t0){e=o[i]}return{text:n.formatter?n.formatter(t,e,i,a):t.name+": "+t.data,color:t.color,legendShape:a.extra.tooltip.legendShape=="auto"?t.legendShape:a.extra.tooltip.legendShape}});var h={x:Math.round(s.x),y:Math.round(s.y)};return{textList:e,offset:h}}function getMixToolTipData(t,e,a,i){var r=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};var o=e.chartData.xAxisPoints[a]+e.chartData.eachSpacing/2;var n=t.map(function(t){return{text:r.formatter?r.formatter(t,i[a],a,e):t.name+": "+t.data,color:t.color,disableLegend:t.disableLegend?true:false,legendShape:e.extra.tooltip.legendShape=="auto"?t.legendShape:e.extra.tooltip.legendShape}});n=n.filter(function(t){if(t.disableLegend!==true){return t}});var l={x:Math.round(o),y:0};return{textList:n,offset:l}}function getCandleToolTipData(o,e,n,l,i,t){var r=arguments.length>6&&arguments[6]!==undefined?arguments[6]:{};var a=n.chartData.calPoints;let s=t.color.upFill;let h=t.color.downFill;let c=[s,s,h,s];var d=[];e.map(function(t){if(l==0){if(t.data[1]-t.data[0]<0){c[1]=h}else{c[1]=s}}else{if(t.data[0]o[l-1][1]){c[2]=s}if(t.data[3]4&&arguments[4]!==undefined?arguments[4]:0;var l={index:-1,group:[]};var i=e.chartData.eachSpacing/2;let r=[];if(n&&n.length>0){if(!e.categories){i=0}else{for(let t=1;tt){l.index=e}})}}}return l}function findBarChartCurrentIndex(a,t,e,i){var r=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0;var o={index:-1,group:[]};var n=e.chartData.eachSpacing/2;let l=e.chartData.yAxisPoints;if(t&&t.length>0){if(isInExactChartArea(a,e,i)){l.forEach(function(t,e){if(a.y+r+n>t){o.index=e}})}}return o}function findLegendIndex(o,t,e){let n=-1;let l=0;if(isInExactLegendArea(o,t.area)){let i=t.points;let r=-1;for(let t=0,e=i.length;tt[0]-l&&o.xt[1]-l&&o.ye.start.x&&t.xe.start.y&&t.y=e.area[3]-10&&t.y>=e.area[0]&&t.y<=e.height-e.area[2]}function findRadarChartCurrentIndex(t,e,a){var r=2*Math.PI/a;var o=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var n=function t(e){if(e<0){e+=2*Math.PI}if(e>2*Math.PI){e-=2*Math.PI}return e};var l=Math.atan2(e.center.y-t.y,t.x-e.center.x);l=-1*l;if(l<0){l+=2*Math.PI}var i=e.angleList.map(function(t){t=n(-1*t);return t});i.forEach(function(t,e){var a=n(t-r/2);var i=n(t+r/2);if(i=a&&l<=i||l+2*Math.PI>=a&&l+2*Math.PI<=i){o=e}})}return o}function findFunnelChartCurrentIndex(t,e){var a=-1;for(var i=0,r=e.series.length;io.funnelArea[0]&&t.xo.funnelArea[1]&&t.yo.area[0]&&t.xo.area[1]&&t.ys.width-s.area[1]-s.area[3]){i.push(n);o.push(r-s.legend.itemGap*s.pix);r=e;n=[t]}else{r+=e;n.push(t)}}if(n.length){i.push(n);o.push(r-s.legend.itemGap*s.pix);c.widthArr=o;let t=Math.max.apply(null,o);switch(s.legend.float){case"left":c.area.start.x=s.area[3];c.area.end.x=s.area[3]+t+2*d;break;case"right":c.area.start.x=s.width-s.area[1]-t-2*d;c.area.end.x=s.width-s.area[1];break;default:c.area.start.x=(s.width-t)/2-d;c.area.end.x=(s.width+t)/2+d}c.area.width=t+2*d;c.area.wholeWidth=t+2*d;c.area.height=i.length*u+2*d;c.area.wholeHeight=i.length*u+2*d+2*x;c.points=i}}else{let t=l.length;let e=s.height-s.area[0]-s.area[2]-2*x-2*d;let a=Math.min(Math.floor(e/u),t);c.area.height=a*u+d*2;c.area.wholeHeight=a*u+d*2;switch(s.legend.float){case"top":c.area.start.y=s.area[0]+x;c.area.end.y=s.area[0]+x+c.area.height;break;case"bottom":c.area.start.y=s.height-s.area[2]-x-c.area.height;c.area.end.y=s.height-s.area[2]-x;break;default:c.area.start.y=(s.height-c.area.height)/2;c.area.end.y=(s.height+c.area.height)/2}let i=t%a===0?t/a:Math.floor(t/a+1);let r=[];for(let e=0;ei){i=t}}c.widthArr.push(i);c.heightArr.push(a.length*u+d*2)}let e=0;for(let t=0;t4&&arguments[4]!==undefined?arguments[4]:-1;var i;if(c=="stack"){i=dataCombineStack(t,e.categories.length)}else{i=dataCombine(t)}var r=[];i=i.filter(function(t){if(typeof t==="object"&&t!==null){if(t.constructor.toString().indexOf("Array")>-1){return t!==null}else{return t.value!==null}}else{return t!==null}});i.map(function(t){if(typeof t==="object"){if(t.constructor.toString().indexOf("Array")>-1){if(e.type=="candle"){t.map(function(t){r.push(t)})}else{r.push(t[0])}}else{r.push(t.value)}}else{r.push(t)}});var o=0;var n=0;if(r.length>0){o=Math.min.apply(this,r);n=Math.max.apply(this,r)}if(a>-1){if(typeof e.xAxis.data[a].min==="number"){o=Math.min(e.xAxis.data[a].min,o)}if(typeof e.xAxis.data[a].max==="number"){n=Math.max(e.xAxis.data[a].max,n)}}else{if(typeof e.xAxis.min==="number"){o=Math.min(e.xAxis.min,o)}if(typeof e.xAxis.max==="number"){n=Math.max(e.xAxis.max,n)}}if(o===n){var d=n||10;n+=d}var l=o;var x=n;var f=[];var p=(x-l)/e.xAxis.splitNumber;for(var s=0;s<=e.xAxis.splitNumber;s++){f.push(l+p*s)}return f}function calXAxisData(t,e,a,i){var r=assign({},{type:""},e.extra.bar);var o={angle:0,xAxisHeight:e.xAxis.lineHeight*e.pix+e.xAxis.marginTop*e.pix};o.ranges=getXAxisTextList(t,e,a,r.type);o.rangesFormat=o.ranges.map(function(t){t=util.toFixed(t,2);return t});var n=o.ranges.map(function(t){t=util.toFixed(t,2);return t});o=Object.assign(o,getXAxisPoints(n,e,a));var l=o.eachSpacing;var s=n.map(function(t){return measureText(t,e.xAxis.fontSize*e.pix,i)});if(e.xAxis.disabled===true){o.xAxisHeight=0}return o}function getRadarDataPoints(r,o,n,a,t){var l=arguments.length>5&&arguments[5]!==undefined?arguments[5]:1;var e=t.extra.radar||{};e.max=e.max||0;var s=Math.max(e.max,Math.max.apply(null,dataCombine(a)));var h=[];for(let e=0;e2&&arguments[2]!==undefined?arguments[2]:1;var o=0;var n=0;for(let e=0;e4&&arguments[4]!==undefined?arguments[4]:1;for(let t=0;t4&&arguments[4]!==undefined?arguments[4]:1;var l=0;var s=0;var h=[];for(let e=0;e2&&arguments[2]!==undefined?arguments[2]:1;if(o==1){o=.999999}for(let a=0;a=2){t._proportion_=t._proportion_%2}}return i}function getGaugeArcbarDataPoints(i,r){var o=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;if(o==1){o=.999999}for(let a=0;a=2){t._proportion_=t._proportion_%2}}return i}function getGaugeAxisPoints(e,a,t){let i;if(t=2){e[t]._endAngle_=e[t]._endAngle_%2}r=e[t]._endAngle_}return e}function getGaugeDataPoints(i,r,o){let n=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;for(let a=0;a=o.oldData){e._proportion_=(e._endAngle_-e._oldAngle_)*n+o.oldAngle}else{e._proportion_=e._oldAngle_-(e._oldAngle_-e._endAngle_)*n}if(e._proportion_>=2){e._proportion_=e._proportion_%2}}return i}function getPieTextMaxLength(i,r,o,n){i=getPieDataPoints(i);let l=0;for(let a=0;a0){t.width=Math.min(t.width,+n.extra.mix.column.width*n.pix)}if(n.extra.column&&n.extra.column.width&&+n.extra.column.width>0){t.width=Math.min(t.width,+n.extra.column.width*n.pix)}if(t.width<=0){t.width=1}t.x+=(o+.5-r/2)*(t.width+e);return t})}function fixBarData(t,i,r,o,e,n){return t.map(function(t){if(t===null){return null}var e=0;var a=0;e=n.extra.bar.seriesGap*n.pix||0;a=n.extra.bar.categoryGap*n.pix||0;e=Math.min(e,i/r);a=Math.min(a,i/r);t.width=Math.ceil((i-2*a-e*(r-1))/r);if(n.extra.bar&&n.extra.bar.width&&+n.extra.bar.width>0){t.width=Math.min(t.width,+n.extra.bar.width*n.pix)}if(t.width<=0){t.width=1}t.y+=(o+.5-r/2)*(t.width+e);return t})}function fixColumeMeterData(t,e,a,i,r,o,n){var l=o.extra.column.categoryGap*o.pix||0;return t.map(function(t){if(t===null){return null}t.width=e-2*l;if(o.extra.column&&o.extra.column.width&&+o.extra.column.width>0){t.width=Math.min(t.width,+o.extra.column.width*o.pix)}if(i>0){t.width-=n}return t})}function fixColumeStackData(t,a,e,i,r,o,n){var l=o.extra.column.categoryGap*o.pix||0;return t.map(function(t,e){if(t===null){return null}t.width=Math.ceil(a-2*l);if(o.extra.column&&o.extra.column.width&&+o.extra.column.width>0){t.width=Math.min(t.width,+o.extra.column.width*o.pix)}if(t.width<=0){t.width=1}return t})}function fixBarStackData(t,a,e,i,r,o,n){var l=o.extra.bar.categoryGap*o.pix||0;return t.map(function(t,e){if(t===null){return null}t.width=Math.ceil(a-2*l);if(o.extra.bar&&o.extra.bar.width&&+o.extra.bar.width>0){t.width=Math.min(t.width,+o.extra.bar.width*o.pix)}if(t.width<=0){t.width=1}return t})}function getXAxisPoints(t,e,h){var a=e.width-e.area[1]-e.area[3];var i=e.enableScroll?Math.min(e.xAxis.itemCount,t.length):t.length;if((e.type=="line"||e.type=="area"||e.type=="scatter"||e.type=="bubble"||e.type=="bar")&&i>1&&e.xAxis.boundaryGap=="justify"){i-=1}var r=0;if(e.type=="mount"&&e.extra&&e.extra.mount&&e.extra.mount.widthRatio&&e.extra.mount.widthRatio>1){if(e.extra.mount.widthRatio>2)e.extra.mount.widthRatio=2;r=e.extra.mount.widthRatio-1;i+=r}var o=a/i;var n=[];var l=e.area[3];var s=e.width-e.area[1];t.forEach(function(t,e){n.push(l+r/2*o+e*o)});if(e.xAxis.boundaryGap!=="justify"){if(e.enableScroll===true){n.push(l+r*o+t.length*o)}else{n.push(s)}}return{xAxisPoints:n,startX:l,endX:s,eachSpacing:o}}function getCandleDataPoints(t,l,s,h,c,d,a){var x=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var e=[];var f=d.height-d.area[0]-d.area[2];t.forEach(function(t,o){if(t===null){e.push(null)}else{var n=[];t.forEach(function(t,e){var a={};a.x=h[o]+Math.round(c/2);var i=t.value||t;var r=f*(i-l)/(s-l);r*=x;a.y=d.height-Math.round(r)-d.area[2];n.push(a)});e.push(n)}});return e}function getDataPoints(t,a,n,l,s,h,e){var c=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var d="center";if(h.type=="line"||h.type=="area"||h.type=="scatter"||h.type=="bubble"){d=h.xAxis.boundaryGap}var x=[];var f=h.height-h.area[0]-h.area[2];var p=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){x.push(null)}else{var r={};r.color=i.color;r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+p*(i[0]-e)/(a-e);if(h.type=="bubble"){r.r=i[2];r.t=i[3]}}else{o=i.value}}if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);e*=c;r.y=h.height-e-h.area[2];x.push(r)}});return x}function getLineDataPoints(t,a,n,l,s,h,e,p,c){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=h.xAxis.boundaryGap;var x=[];var f=h.height-h.area[0]-h.area[2];var u=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){x.push(null)}else{var r={};r.color=i.color;if(p.animation=="vertical"){r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+u*(i[0]-e)/(a-e)}else{o=i.value}}if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);e*=c;r.y=h.height-e-h.area[2];x.push(r)}else{r.x=l[0]+s*t*c;var o=i;if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);r.y=h.height-e-h.area[2];x.push(r)}}});return x}function getColumnDataPoints(t,a,n,l,s,h,e,i,c){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=[];var x=h.height-h.area[0]-h.area[2];var f=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){d.push(null)}else{var r={};r.color=i.color;r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+f*(i[0]-e)/(a-e)}else{o=i.value}}r.x+=s/2;var e=x*(o*c-a)/(n-a);r.y=h.height-e-h.area[2];d.push(r)}});return d}function getMountDataPoints(t,o,n,l,s,h,e,a){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=[];var x=h.height-h.area[0]-h.area[2];var i=h.width-h.area[1]-h.area[3];var f=s*e.widthRatio;t.forEach(function(t,e){if(t===null){d.push(null)}else{var a={};a.color=t.color;a.x=l[e];a.x+=s/2;var i=t.data;var r=x*(i*c-o)/(n-o);a.y=h.height-r-h.area[2];a.value=i;a.width=f;d.push(a)}});return d}function getBarDataPoints(t,o,n,l,e,s,a){var h=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var c=[];var i=s.height-s.area[0]-s.area[2];var d=s.width-s.area[1]-s.area[3];t.forEach(function(t,e){if(t===null){c.push(null)}else{var a={};a.color=t.color;a.y=l[e];var i=t;if(typeof t==="object"&&t!==null){i=t.value}var r=d*(i-o)/(n-o);r*=h;a.height=r;a.value=i;a.x=r+s.area[3];c.push(a)}});return c}function getStackDataPoints(t,s,h,c,g,d,e,x,y){var f=arguments.length>9&&arguments[9]!==undefined?arguments[9]:1;var p=[];var u=d.height-d.area[0]-d.area[2];t.forEach(function(t,e){if(t===null){p.push(null)}else{var a={};a.color=t.color;a.x=c[e]+Math.round(g/2);if(x>0){var i=0;for(let t=0;t<=x;t++){i+=y[t].data[e]}var r=i-t;var o=u*(i-s)/(h-s);var n=u*(r-s)/(h-s)}else{var i=t;if(typeof t==="object"&&t!==null){i=t.value}var o=u*(i-s)/(h-s);var n=0}var l=n;o*=f;l*=f;a.y=d.height-Math.round(o)-d.area[2];a.y0=d.height-Math.round(l)-d.area[2];p.push(a)}});return p}function getBarStackDataPoints(t,s,h,c,e,d,a,x,g){var f=arguments.length>9&&arguments[9]!==undefined?arguments[9]:1;var p=[];var u=d.width-d.area[1]-d.area[3];t.forEach(function(t,e){if(t===null){p.push(null)}else{var a={};a.color=t.color;a.y=c[e];if(x>0){var i=0;for(let t=0;t<=x;t++){i+=g[t].data[e]}var r=i-t;var o=u*(i-s)/(h-s);var n=u*(r-s)/(h-s)}else{var i=t;if(typeof t==="object"&&t!==null){i=t.value}var o=u*(i-s)/(h-s);var n=0}var l=n;o*=f;l*=f;a.height=o-l;a.x=d.area[3]+o;a.x0=d.area[3]+l;p.push(a)}});return p}function getYAxisTextList(t,e,h,c,a){var d=arguments.length>5&&arguments[5]!==undefined?arguments[5]:-1;var i;if(c=="stack"){i=dataCombineStack(t,e.categories.length)}else{i=dataCombine(t)}var r=[];i=i.filter(function(t){if(typeof t==="object"&&t!==null){if(t.constructor.toString().indexOf("Array")>-1){return t!==null}else{return t.value!==null}}else{return t!==null}});i.map(function(t){if(typeof t==="object"){if(t.constructor.toString().indexOf("Array")>-1){if(e.type=="candle"){t.map(function(t){r.push(t)})}else{r.push(t[1])}}else{r.push(t.value)}}else{r.push(t)}});var o=a.min||0;var n=a.max||0;if(r.length>0){o=Math.min.apply(this,r);n=Math.max.apply(this,r)}if(o===n){if(n==0){n=10}else{o=0}}var l=getDataRange(o,n);var x=a.min===undefined||a.min===null?l.minRange:a.min;var f=a.max===undefined||a.max===null?l.maxRange:a.max;var p=(f-x)/e.yAxis.splitNumber;var u=[];for(var s=0;s<=e.yAxis.splitNumber;s++){u.push(x+p*s)}return u.reverse()}function calYAxisData(a,o,e,n){var l=assign({},{type:""},o.extra.column);var t=o.yAxis.data.length;var s=new Array(t);if(t>0){for(let e=0;e{return t+(i.unit||"")}}i.categories=i.categories||o.categories;h[r]=i.categories}else{if(!i.formatter){i.formatter=(t,e,a)=>{return util.toFixed(t,i.tofix||0)+(i.unit||"")}}h[r]=getYAxisTextList(s[r],o,e,l.type,i,r)}let a=i.fontSize*o.pix||e.fontSize;d[r]={position:i.position?i.position:"left",width:0};c[r]=h[r].map(function(t,e){t=i.formatter(t,e,o);d[r].width=Math.max(d[r].width,measureText(t,a,n)+5);return t});let t=i.calibration?4*o.pix:0;d[r].width+=t+3*o.pix;if(i.disabled===true){d[r].width=0}}}else{var h=new Array(1);var c=new Array(1);var d=new Array(1);if(o.type==="bar"){h[0]=o.categories;if(!o.yAxis.formatter){o.yAxis.formatter=(t,e,a)=>{return t+(a.yAxis.unit||"")}}}else{if(!o.yAxis.formatter){o.yAxis.formatter=(t,e,a)=>{return t.toFixed(a.yAxis.tofix)+(a.yAxis.unit||"")}}h[0]=getYAxisTextList(a,o,e,l.type,{})}d[0]={position:"left",width:0};var i=o.yAxis.fontSize*o.pix||e.fontSize;c[0]=h[0].map(function(t,e){t=o.yAxis.formatter(t,e,o);d[0].width=Math.max(d[0].width,measureText(t,i,n)+5);return t});d[0].width+=3*o.pix;if(o.yAxis.disabled===true){d[0]={position:"left",width:0};o.yAxis.data[0]={disabled:true}}else{o.yAxis.data[0]={disabled:false,position:"left",max:o.yAxis.max,min:o.yAxis.min,formatter:o.yAxis.formatter};if(o.type==="bar"){o.yAxis.data[0].categories=o.categories;o.yAxis.data[0].type="categories"}}}return{rangesFormat:c,ranges:h,yAxisWidth:d}}function calTooltipYAxisData(r,t,o,e,a){let n=[].concat(o.chartData.yAxisData.ranges);let l=o.height-o.area[0]-o.area[2];let s=o.area[0];let h=[];for(let i=0;i0&&r.tooltip.group.includes(n)==false){return}var l=typeof r.tooltip.index==="number"?r.tooltip.index:r.tooltip.index[r.tooltip.group.indexOf(n)];i.beginPath();if(o.activeType=="hollow"){i.setStrokeStyle(e);i.setFillStyle(r.background);i.setLineWidth(2*r.pix)}else{i.setStrokeStyle("#ffffff");i.setFillStyle(e);i.setLineWidth(1*r.pix)}if(a==="diamond"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x,t.y-4.5);i.lineTo(t.x-4.5,t.y);i.lineTo(t.x,t.y+4.5);i.lineTo(t.x+4.5,t.y);i.lineTo(t.x,t.y-4.5)}})}else if(a==="circle"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x+2.5*r.pix,t.y);i.arc(t.x,t.y,3*r.pix,0,2*Math.PI,false)}})}else if(a==="square"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x-3.5,t.y-3.5);i.rect(t.x-3.5,t.y-3.5,7,7)}})}else if(a==="triangle"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x,t.y-4.5);i.lineTo(t.x-4.5,t.y+4.5);i.lineTo(t.x+4.5,t.y+4.5);i.lineTo(t.x,t.y-4.5)}})}else if(a==="none"){return}i.closePath();i.fill();i.stroke()}function drawRingTitle(t,e,a,i){var r=t.title.fontSize||e.titleFontSize;var o=t.subtitle.fontSize||e.subtitleFontSize;var n=t.title.name||"";var l=t.subtitle.name||"";var c=t.title.color||t.fontColor;var d=t.subtitle.color||t.fontColor;var x=n?r:0;var f=l?o:0;var s=5;if(l){var p=measureText(l,o*t.pix,a);var u=i.x-p/2+(t.subtitle.offsetX||0)*t.pix;var h=i.y+o*t.pix/2+(t.subtitle.offsetY||0)*t.pix;if(n){h+=(x*t.pix+s)/2}a.beginPath();a.setFontSize(o*t.pix);a.setFillStyle(d);a.fillText(l,u,h);a.closePath();a.stroke()}if(n){var g=measureText(n,r*t.pix,a);var y=i.x-g/2+(t.title.offsetX||0);var v=i.y+r*t.pix/2+(t.title.offsetY||0)*t.pix;if(l){v-=(f*t.pix+s)/2}a.beginPath();a.setFontSize(r*t.pix);a.setFillStyle(c);a.fillText(n,y,v);a.closePath();a.stroke()}}function drawPointText(t,o,n,l,s){var h=o.data;var c=o.textOffset?o.textOffset:0;t.forEach(function(t,e){if(t!==null){l.beginPath();var a=o.textSize?o.textSize*s.pix:n.fontSize;l.setFontSize(a);l.setFillStyle(o.textColor||s.fontColor);var i=h[e];if(typeof h[e]==="object"&&h[e]!==null){if(h[e].constructor.toString().indexOf("Array")>-1){i=h[e][1]}else{i=h[e].value}}var r=o.formatter?o.formatter(i,e,o,s):i;l.setTextAlign("center");l.fillText(String(r),t.x,t.y-4+c*s.pix);l.closePath();l.stroke();l.setTextAlign("left")}})}function drawColumePointText(t,n,l,s,h){var c=n.data;var d=n.textOffset?n.textOffset:0;var x=h.extra.column.labelPosition;t.forEach(function(t,e){if(t!==null){s.beginPath();var a=n.textSize?n.textSize*h.pix:l.fontSize;s.setFontSize(a);s.setFillStyle(n.textColor||h.fontColor);var i=c[e];if(typeof c[e]==="object"&&c[e]!==null){if(c[e].constructor.toString().indexOf("Array")>-1){i=c[e][1]}else{i=c[e].value}}var r=n.formatter?n.formatter(i,e,n,h):i;s.setTextAlign("center");var o=t.y-4*h.pix+d*h.pix;if(t.y>n.zeroPoints){o=t.y+d*h.pix+a}if(x=="insideTop"){o=t.y+a+d*h.pix;if(t.y>n.zeroPoints){o=t.y-d*h.pix-4*h.pix}}if(x=="center"){o=t.y+d*h.pix+(h.height-h.area[2]-t.y+a)/2;if(n.zeroPointsn.zeroPoints){o=t.y-d*h.pix-(t.y-n.zeroPoints-a)/2}if(h.extra.column.type=="stack"){o=t.y+d*h.pix+(t.y0-t.y+a)/2}}if(x=="bottom"){o=h.height-h.area[2]+d*h.pix-4*h.pix;if(n.zeroPointsn.zeroPoints){o=n.zeroPoints-d*h.pix+a+2*h.pix}if(h.extra.column.type=="stack"){o=t.y0+d*h.pix-4*h.pix}}s.fillText(String(r),t.x,o);s.closePath();s.stroke();s.setTextAlign("left")}})}function drawMountPointText(t,n,l,s,h,c){var e=n.data;var d=n.textOffset?n.textOffset:0;var a=h.extra.mount.labelPosition;t.forEach(function(t,e){if(t!==null){s.beginPath();var a=n[e].textSize?n[e].textSize*h.pix:l.fontSize;s.setFontSize(a);s.setFillStyle(n[e].textColor||h.fontColor);var i=t.value;var r=n[e].formatter?n[e].formatter(i,e,n,h):i;s.setTextAlign("center");var o=t.y-4*h.pix+d*h.pix;if(t.y>c){o=t.y+d*h.pix+a}s.fillText(String(r),t.x,o);s.closePath();s.stroke();s.setTextAlign("left")}})}function drawBarPointText(t,o,n,l,s){var h=o.data;var e=o.textOffset?o.textOffset:0;t.forEach(function(t,e){if(t!==null){l.beginPath();var a=o.textSize?o.textSize*s.pix:n.fontSize;l.setFontSize(a);l.setFillStyle(o.textColor||s.fontColor);var i=h[e];if(typeof h[e]==="object"&&h[e]!==null){i=h[e].value}var r=o.formatter?o.formatter(i,e,o,s):i;l.setTextAlign("left");l.fillText(String(r),t.x+4*s.pix,t.y+a/2-3);l.closePath();l.stroke()}})}function drawGaugeLabel(e,a,i,r,o,n){a-=e.width/2+e.labelOffset*r.pix;a=a<10?10:a;let t;if(e.endAngle=2){l=l%2}s+=x}}function drawRadarLabel(t,s,h,c,d,x){var f=c.extra.radar||{};t.forEach(function(t,e){if(f.labelPointShow===true&&c.categories[e]!==""){var a={x:s*Math.cos(t),y:s*Math.sin(t)};var i=convertCoordinateOrigin(a.x,a.y,h);x.setFillStyle(f.labelPointColor);x.beginPath();x.arc(i.x,i.y,f.labelPointRadius*c.pix,0,2*Math.PI,false);x.closePath();x.fill()}if(f.labelShow===true){var r={x:(s+d.radarLabelTextMargin*c.pix)*Math.cos(t),y:(s+d.radarLabelTextMargin*c.pix)*Math.sin(t)};var o=convertCoordinateOrigin(r.x,r.y,h);var n=o.x;var l=o.y;if(util.approximatelyEqual(r.x,0)){n-=measureText(c.categories[e]||"",d.fontSize,x)/2}else if(r.x<0){n-=measureText(c.categories[e]||"",d.fontSize,x)}x.beginPath();x.setFontSize(d.fontSize);x.setFillStyle(f.labelColor||c.fontColor);x.fillText(c.categories[e]||"",n,l+d.fontSize/2);x.closePath();x.stroke()}})}function drawPieText(n,d,x,f,t,l){var p=x.pieChartLinePadding;var u=[];var g=null;var y=n.map(function(t,e){var a=t.formatter?t.formatter(t,e,n,d):util.toFixed(t._proportion_.toFixed(4)*100)+"%";a=t.labelText?t.labelText:a;var i=2*Math.PI-(t._start_+2*Math.PI*t._proportion_/2);if(t._rose_proportion_){i=2*Math.PI-(t._start_+2*Math.PI*t._rose_proportion_/2)}var r=t.color;var o=t._radius_;return{arc:i,text:a,color:r,radius:o,textColor:t.textColor,textSize:t.textSize,labelShow:t.labelShow}});for(let c=0;c=0?e+x.pieChartTextPadding:e-x.pieChartTextPadding;let n=a;let l=measureText(t.text,t.textSize*d.pix||x.fontSize,f);let s=n;if(g&&util.isSameXCoordinateArea(g.start,{x:o})){if(o>0){s=Math.min(n,g.start.y)}else if(e<0){s=Math.max(n,g.start.y)}else{if(n>0){s=Math.max(n,g.start.y)}else{s=Math.min(n,g.start.y)}}}if(o<0){o-=l}let h={lineStart:{x:i,y:r},lineEnd:{x:e,y:a},start:{x:o,y:s},width:l,height:x.fontSize,text:t.text,color:t.color,textColor:t.textColor,textSize:t.textSize};g=avoidCollision(h,g);u.push(g)}for(let n=0;nr?r:o.activeWidth;var n=e.area[0];var l=e.height-e.area[2];i.beginPath();i.setFillStyle(hexToRgb(o.activeBgColor,o.activeBgOpacity));i.rect(t-o.activeWidth/2,n,o.activeWidth,l-n);i.closePath();i.fill();i.setFillStyle("#FFFFFF")}function drawBarToolTipSplitArea(t,e,a,i,r){var o=assign({},{activeBgColor:"#000000",activeBgOpacity:.08},e.extra.bar);var n=e.area[3];var l=e.width-e.area[1];i.beginPath();i.setFillStyle(hexToRgb(o.activeBgColor,o.activeBgOpacity));i.rect(n,t-r/2,l-n,r);i.closePath();i.fill();i.setFillStyle("#FFFFFF")}function drawToolTip(e,r,o,a,n,i,f){var l=assign({},{showBox:true,showArrow:true,showCategory:false,bgColor:"#000000",bgOpacity:.7,borderColor:"#000000",borderWidth:0,borderRadius:0,borderOpacity:.7,boxPadding:3,fontColor:"#FFFFFF",fontSize:13,lineHeight:20,legendShow:true,legendShape:"auto",splitLine:true},o.extra.tooltip);if(l.showCategory==true&&o.categories){e.unshift({text:o.categories[o.tooltip.index],color:null})}var s=l.fontSize*o.pix;var p=l.lineHeight*o.pix;var h=l.boxPadding*o.pix;var c=s;var u=5*o.pix;if(l.legendShow==false){c=0;u=0}var d=l.showArrow?8*o.pix:0;var g=false;if(o.type=="line"||o.type=="mount"||o.type=="area"||o.type=="candle"||o.type=="mix"){if(l.splitLine==true){drawToolTipSplitLine(o.tooltip.offset.x,o,a,n)}}r=assign({x:0,y:0},r);r.y-=8*o.pix;var y=e.map(function(t){return measureText(t.text,s,n)});var x=c+u+4*h+Math.max.apply(null,y);var v=2*h+e.length*p;if(l.showBox==false){return}if(r.x-Math.abs(o._scrollDistance_||0)+d+x>o.width){g=true}if(v+r.y>o.height){r.y=o.height-v}n.beginPath();n.setFillStyle(hexToRgb(l.bgColor,l.bgOpacity));n.setLineWidth(l.borderWidth*o.pix);n.setStrokeStyle(hexToRgb(l.borderColor,l.borderOpacity));var t=l.borderRadius;if(g){if(x+d>o.width){r.x=o.width+Math.abs(o._scrollDistance_||0)+d+(x-o.width)}if(x>r.x){r.x=o.width+Math.abs(o._scrollDistance_||0)+d+(x-o.width)}if(l.showArrow){n.moveTo(r.x,r.y+10*o.pix);n.lineTo(r.x-d,r.y+10*o.pix+5*o.pix)}n.arc(r.x-d-t,r.y+v-t,t,0,Math.PI/2,false);n.arc(r.x-d-Math.round(x)+t,r.y+v-t,t,Math.PI/2,Math.PI,false);n.arc(r.x-d-Math.round(x)+t,r.y+t,t,-Math.PI,-Math.PI/2,false);n.arc(r.x-d-t,r.y+t,t,-Math.PI/2,0,false);if(l.showArrow){n.lineTo(r.x-d,r.y+10*o.pix-5*o.pix);n.lineTo(r.x,r.y+10*o.pix)}}else{if(l.showArrow){n.moveTo(r.x,r.y+10*o.pix);n.lineTo(r.x+d,r.y+10*o.pix-5*o.pix)}n.arc(r.x+d+t,r.y+t,t,-Math.PI,-Math.PI/2,false);n.arc(r.x+d+Math.round(x)-t,r.y+t,t,-Math.PI/2,0,false);n.arc(r.x+d+Math.round(x)-t,r.y+v-t,t,0,Math.PI/2,false);n.arc(r.x+d+t,r.y+v-t,t,Math.PI/2,Math.PI,false);if(l.showArrow){n.lineTo(r.x+d,r.y+10*o.pix+5*o.pix);n.lineTo(r.x,r.y+10*o.pix)}}n.closePath();n.fill();if(l.borderWidth>0){n.stroke()}if(l.legendShow){e.forEach(function(t,e){if(t.color!==null){n.beginPath();n.setFillStyle(t.color);var a=r.x+d+2*h;var i=r.y+(p-s)/2+p*e+h+1;if(g){a=r.x-x-d+2*h}switch(t.legendShape){case"line":n.moveTo(a,i+.5*c-2*o.pix);n.fillRect(a,i+.5*c-2*o.pix,c,4*o.pix);break;case"triangle":n.moveTo(a+7.5*o.pix,i+.5*c-5*o.pix);n.lineTo(a+2.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+12.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+7.5*o.pix,i+.5*c-5*o.pix);break;case"diamond":n.moveTo(a+7.5*o.pix,i+.5*c-5*o.pix);n.lineTo(a+2.5*o.pix,i+.5*c);n.lineTo(a+7.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+12.5*o.pix,i+.5*c);n.lineTo(a+7.5*o.pix,i+.5*c-5*o.pix);break;case"circle":n.moveTo(a+7.5*o.pix,i+.5*c);n.arc(a+7.5*o.pix,i+.5*c,5*o.pix,0,2*Math.PI);break;case"rect":n.moveTo(a,i+.5*c-5*o.pix);n.fillRect(a,i+.5*c-5*o.pix,15*o.pix,10*o.pix);break;case"square":n.moveTo(a+2*o.pix,i+.5*c-5*o.pix);n.fillRect(a+2*o.pix,i+.5*c-5*o.pix,10*o.pix,10*o.pix);break;default:n.moveTo(a,i+.5*c-5*o.pix);n.fillRect(a,i+.5*c-5*o.pix,15*o.pix,10*o.pix)}n.closePath();n.fill()}})}e.forEach(function(t,e){var a=r.x+d+2*h+c+u;if(g){a=r.x-x-d+2*h+c+u}var i=r.y+p*e+(p-s)/2-1+h+s;n.beginPath();n.setFontSize(s);n.setTextBaseline("normal");n.setFillStyle(l.fontColor);n.fillText(t.text,a,i);n.closePath();n.stroke()})}function drawColumnDataPoints(T,b,S,w){let A=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let t=b.chartData.xAxisData,P=t.xAxisPoints,C=t.eachSpacing;let D=assign({},{type:"group",width:C/2,meterBorder:4,meterFillColor:"#FFFFFF",barBorderCircle:false,barBorderRadius:[],seriesGap:2,linearType:"none",linearOpacity:1,customColor:[],colorStop:0,labelPosition:"outside"},b.extra.column);let M=[];w.save();let L=-2;let F=P.length+2;if(b._scrollDistance_&&b._scrollDistance_!==0&&b.enableScroll===true){w.translate(b._scrollDistance_,0);L=Math.floor(-b._scrollDistance_/C)-2;F=L+b.xAxis.itemCount+4}if(b.tooltip&&b.tooltip.textList&&b.tooltip.textList.length&&A===1){drawToolTipSplitArea(b.tooltip.offset.x,b,S,w,C)}D.customColor=fillCustomColor(D.linearType,D.customColor,T,S);T.forEach(function(a,i){let e,t,o;e=[].concat(b.chartData.yAxisData.ranges[a.index]);t=e.pop();o=e.shift();let x=b.height-b.area[0]-b.area[2];let f=x*(0-t)/(o-t);let n=b.height-Math.round(f)-b.area[2];a.zeroPoints=n;var p=a.data;switch(D.type){case"group":var r=getColumnDataPoints(p,t,o,P,C,b,S,n,A);var u=getStackDataPoints(p,t,o,P,C,b,S,i,T,A);M.push(u);r=fixColumeData(r,C,T.length,i,S,b);for(let t=0;tL&&tn?n:o.y;const d=o.width;const s=Math.abs(n-o.y);if(D.barBorderCircle){D.barBorderRadius=[d/2,d/2,0,0]}if(o.y>n){D.barBorderRadius=[0,0,d/2,d/2]}let[t,e,a,i]=D.barBorderRadius;let r=Math.min(d/2,s/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;w.arc(h+t,c+t,t,-Math.PI,-Math.PI/2);w.arc(h+d-e,c+e,e,-Math.PI/2,0);w.arc(h+d-a,c+s-a,a,0,Math.PI/2);w.arc(h+i,c+s-i,i,Math.PI/2,Math.PI)}else{w.moveTo(l,o.y);w.lineTo(l+o.width,o.y);w.lineTo(l+o.width,n);w.lineTo(l,n);w.lineTo(l,o.y);w.setLineWidth(1);w.setStrokeStyle(y)}w.setFillStyle(g);w.closePath();w.fill()}};break;case"stack":var r=getStackDataPoints(p,t,o,P,C,b,S,i,T,A);M.push(r);r=fixColumeStackData(r,C,T.length,i,S,b,T);for(let e=0;eL&&e0){s-=m}w.setFillStyle(g);w.moveTo(l,t.y);w.fillRect(l,t.y,t.width,s);w.closePath();w.fill()}};break;case"meter":var r=getDataPoints(p,t,o,P,C,b,S,A);M.push(r);r=fixColumeMeterData(r,C,T.length,i,S,b,D.meterBorder);for(let t=0;tL&&t0){w.setStrokeStyle(a.color);w.setLineWidth(D.meterBorder*b.pix)}if(i==0){w.setFillStyle(D.meterFillColor)}else{w.setFillStyle(o.color||a.color)}var l=o.x-o.width/2;var s=b.height-o.y-b.area[2];if(D.barBorderRadius&&D.barBorderRadius.length===4||D.barBorderCircle===true){const h=l;const c=o.y;const d=o.width;const s=n-o.y;if(D.barBorderCircle){D.barBorderRadius=[d/2,d/2,0,0]}let[t,e,a,i]=D.barBorderRadius;let r=Math.min(d/2,s/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;w.arc(h+t,c+t,t,-Math.PI,-Math.PI/2);w.arc(h+d-e,c+e,e,-Math.PI/2,0);w.arc(h+d-a,c+s-a,a,0,Math.PI/2);w.arc(h+i,c+s-i,i,Math.PI/2,Math.PI);w.fill()}else{w.moveTo(l,o.y);w.lineTo(l+o.width,o.y);w.lineTo(l+o.width,n);w.lineTo(l,n);w.lineTo(l,o.y);w.fill()}if(i==0&&D.meterBorder>0){w.closePath();w.stroke()}}}break}});if(b.dataLabel!==false&&A===1){T.forEach(function(t,e){let a,i,r;a=[].concat(b.chartData.yAxisData.ranges[t.index]);i=a.pop();r=a.shift();var o=t.data;switch(D.type){case"group":var n=getColumnDataPoints(o,i,r,P,C,b,S,A);n=fixColumeData(n,C,T.length,e,S,b);drawColumePointText(n,t,S,w,b);break;case"stack":var n=getStackDataPoints(o,i,r,P,C,b,S,e,T,A);drawColumePointText(n,t,S,w,b);break;case"meter":var n=getDataPoints(o,i,r,P,C,b,S,A);drawColumePointText(n,t,S,w,b);break}})}w.restore();return{xAxisPoints:P,calPoints:M,eachSpacing:C}}function drawMountDataPoints(i,r,o,n){let f=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let t=r.chartData.xAxisData,p=t.xAxisPoints,l=t.eachSpacing;let s=assign({},{type:"mount",widthRatio:1,borderWidth:1,barBorderCircle:false,barBorderRadius:[],linearType:"none",linearOpacity:1,customColor:[],colorStop:0},r.extra.mount);s.widthRatio=s.widthRatio<=0?0:s.widthRatio;s.widthRatio=s.widthRatio>=2?2:s.widthRatio;let e=[];n.save();let u=-2;let g=p.length+2;if(r._scrollDistance_&&r._scrollDistance_!==0&&r.enableScroll===true){n.translate(r._scrollDistance_,0);u=Math.floor(-r._scrollDistance_/l)-2;g=u+r.xAxis.itemCount+4}s.customColor=fillCustomColor(s.linearType,s.customColor,i,o);let y,v,m;y=[].concat(r.chartData.yAxisData.ranges[0]);v=y.pop();m=y.shift();let T=r.height-r.area[0]-r.area[2];let b=T*(0-v)/(m-v);let h=r.height-Math.round(b)-r.area[2];var c=getMountDataPoints(i,v,m,p,l,r,s,h,f);switch(s.type){case"bar":for(let t=0;tu&&th?h:o.y;const C=o.width;const S=Math.abs(h-o.y);if(s.barBorderCircle){s.barBorderRadius=[C/2,C/2,0,0]}if(o.y>h){s.barBorderRadius=[0,0,C/2,C/2]}let[t,e,a,i]=s.barBorderRadius;let r=Math.min(C/2,S/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;n.arc(A+t,P+t,t,-Math.PI,-Math.PI/2);n.arc(A+C-e,P+e,e,-Math.PI/2,0);n.arc(A+C-a,P+S-a,a,0,Math.PI/2);n.arc(A+i,P+S-i,i,Math.PI/2,Math.PI)}else{n.moveTo(d,o.y);n.lineTo(d+o.width,o.y);n.lineTo(d+o.width,h);n.lineTo(d,h);n.lineTo(d,o.y)}n.setStrokeStyle(w);n.setFillStyle(a);if(s.borderWidth>0){n.setLineWidth(s.borderWidth*r.pix);n.closePath();n.stroke()}n.fill()}};break;case"triangle":for(let e=0;eu&&e0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break;case"mount":for(let e=0;eu&&e0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break;case"sharp":for(let e=0;eu&&e0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break}if(r.dataLabel!==false&&f===1){let t,e,a;t=[].concat(r.chartData.yAxisData.ranges[0]);e=t.pop();a=t.shift();var c=getMountDataPoints(i,e,a,p,l,r,s,h,f);drawMountPointText(c,i,o,n,r,h)}n.restore();return{xAxisPoints:p,calPoints:c,eachSpacing:l}}function drawBarDataPoints(y,v,m,T){let b=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let S=[];let w=(v.height-v.area[0]-v.area[2])/v.categories.length;for(let t=0;tC&&tr?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;T.arc(g+i,c+i,i,-Math.PI,-Math.PI/2);T.arc(o.x-t,c+t,t,-Math.PI/2,0);T.arc(o.x-e,c+h-e,e,0,Math.PI/2);T.arc(g+a,c+h-a,a,Math.PI/2,Math.PI)}else{T.moveTo(n,r);T.lineTo(o.x,r);T.lineTo(o.x,r+o.width);T.lineTo(n,r+o.width);T.lineTo(n,r);T.setLineWidth(1);T.setStrokeStyle(u)}T.setFillStyle(l);T.closePath();T.fill()}};break;case"stack":var i=getBarStackDataPoints(x,e,d,S,w,v,m,t,y,b);P.push(i);i=fixBarStackData(i,w,y.length,t,m,v,y);for(let e=0;eC&&e5&&arguments[5]!==undefined?arguments[5]:1;var s=assign({},{color:{},average:{}},h.extra.candle);s.color=assign({},{upLine:"#f04864",upFill:"#f04864",downLine:"#2fc25b",downFill:"#2fc25b"},s.color);s.average=assign({},{show:false,name:[],day:[],color:c.color},s.average);h.extra.candle=s;let a=h.chartData.xAxisData,x=a.xAxisPoints,f=a.eachSpacing;let y=[];d.save();let p=-2;let v=x.length+2;let u=0;let m=h.width+f;if(h._scrollDistance_&&h._scrollDistance_!==0&&h.enableScroll===true){d.translate(h._scrollDistance_,0);p=Math.floor(-h._scrollDistance_/f)-2;v=p+h.xAxis.itemCount+4;u=-h._scrollDistance_-f*2+h.area[3];m=u+(h.xAxis.itemCount+4)*f}if(s.average.show||t){t.forEach(function(e,t){let a,i,r;a=[].concat(h.chartData.yAxisData.ranges[e.index]);i=a.pop();r=a.shift();var o=e.data;var n=getDataPoints(o,i,r,x,f,h,c,g);var l=splitPoints(n,e);for(let t=0;tu){d.moveTo(t.x,t.y);a=1}if(e>0&&t.x>u&&t.xp&&e0){d.setStrokeStyle(s.color.upLine);d.setFillStyle(s.color.upFill);d.setLineWidth(1*h.pix);d.moveTo(t[3].x,t[3].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[1].x-f/4,t[1].y);d.lineTo(t[0].x-f/4,t[0].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[2].x,t[2].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[0].x+f/4,t[0].y);d.lineTo(t[1].x+f/4,t[1].y);d.lineTo(t[1].x,t[1].y);d.moveTo(t[3].x,t[3].y)}else{d.setStrokeStyle(s.color.downLine);d.setFillStyle(s.color.downFill);d.setLineWidth(1*h.pix);d.moveTo(t[3].x,t[3].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[0].x-f/4,t[0].y);d.lineTo(t[1].x-f/4,t[1].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[2].x,t[2].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[1].x+f/4,t[1].y);d.lineTo(t[0].x+f/4,t[0].y);d.lineTo(t[0].x,t[0].y);d.moveTo(t[3].x,t[3].y)}d.closePath();d.fill();d.stroke()}}});d.restore();return{xAxisPoints:x,calPoints:y,eachSpacing:f}}function drawAreaDataPoints(t,s,h,c){var d=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var x=assign({},{type:"straight",opacity:.2,addLine:false,width:2,gradient:false,activeType:"none"},s.extra.area);let e=s.chartData.xAxisData,f=e.xAxisPoints,p=e.eachSpacing;let y=s.height-s.area[2];let v=[];c.save();let u=0;let g=s.width+p;if(s._scrollDistance_&&s._scrollDistance_!==0&&s.enableScroll===true){c.translate(s._scrollDistance_,0);u=-s._scrollDistance_-p*2+s.area[3];g=u+(s.xAxis.itemCount+4)*p}t.forEach(function(e,t){let a,i,r;a=[].concat(s.chartData.yAxisData.ranges[e.index]);i=a.pop();r=a.shift();let o=e.data;let n=getDataPoints(o,i,r,f,p,s,h,d);v.push(n);let l=splitPoints(n,e);for(let t=0;t1){let t=r[0];let e=r[r.length-1];c.moveTo(t.x,t.y);let i=0;if(x.type==="curve"){for(let a=0;au){c.moveTo(e.x,e.y);i=1}if(a>0&&e.x>u&&e.xu){c.moveTo(t.x,t.y);i=1}if(e>0&&t.x>u&&t.xu){c.moveTo(t.x,t.y);i=1}if(e>0&&t.x>u&&t.xu){c.moveTo(e.x,e.y);i=1}if(a>0&&e.x>u&&e.xu){c.moveTo(t.x,t.y);i=1}if(e>0&&t.x>u&&t.xu){c.moveTo(t.x,t.y);i=1}if(e>0&&t.x>u&&t.x4&&arguments[4]!==undefined?arguments[4]:1;var i=assign({},{type:"circle"},s.extra.scatter);let e=s.chartData.xAxisData,x=e.xAxisPoints,f=e.eachSpacing;var r=[];c.save();let a=0;let o=s.width+f;if(s._scrollDistance_&&s._scrollDistance_!==0&&s.enableScroll===true){c.translate(s._scrollDistance_,0);a=-s._scrollDistance_-f*2+s.area[3];o=a+(s.xAxis.itemCount+4)*f}t.forEach(function(t,e){let a,i,r;a=[].concat(s.chartData.yAxisData.ranges[t.index]);i=a.pop();r=a.shift();var o=t.data;var n=getDataPoints(o,i,r,x,f,s,h,d);c.beginPath();c.setStrokeStyle(t.color);c.setFillStyle(t.color);c.setLineWidth(1*s.pix);var l=t.pointShape;if(l==="diamond"){n.forEach(function(t,e){if(t!==null){c.moveTo(t.x,t.y-4.5);c.lineTo(t.x-4.5,t.y);c.lineTo(t.x,t.y+4.5);c.lineTo(t.x+4.5,t.y);c.lineTo(t.x,t.y-4.5)}})}else if(l==="circle"){n.forEach(function(t,e){if(t!==null){c.moveTo(t.x+2.5*s.pix,t.y);c.arc(t.x,t.y,3*s.pix,0,2*Math.PI,false)}})}else if(l==="square"){n.forEach(function(t,e){if(t!==null){c.moveTo(t.x-3.5,t.y-3.5);c.rect(t.x-3.5,t.y-3.5,7,7)}})}else if(l==="triangle"){n.forEach(function(t,e){if(t!==null){c.moveTo(t.x,t.y-4.5);c.lineTo(t.x-4.5,t.y+4.5);c.lineTo(t.x+4.5,t.y+4.5);c.lineTo(t.x,t.y-4.5)}})}else if(l==="triangle"){return}c.closePath();c.fill();c.stroke()});if(s.dataLabel!==false&&d===1){t.forEach(function(t,e){let a,i,r;a=[].concat(s.chartData.yAxisData.ranges[t.index]);i=a.pop();r=a.shift();var o=t.data;var n=getDataPoints(o,i,r,x,f,s,h,d);drawPointText(n,t,h,c,s)})}c.restore();return{xAxisPoints:x,calPoints:r,eachSpacing:f}}function drawBubbleDataPoints(a,l,s,h){var c=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var d=assign({},{opacity:1,border:2},l.extra.bubble);let t=l.chartData.xAxisData,x=t.xAxisPoints,f=t.eachSpacing;var i=[];h.save();let e=0;let r=l.width+f;if(l._scrollDistance_&&l._scrollDistance_!==0&&l.enableScroll===true){h.translate(l._scrollDistance_,0);e=-l._scrollDistance_-f*2+l.area[3];r=e+(l.xAxis.itemCount+4)*f}a.forEach(function(i,t){let e,a,r;e=[].concat(l.chartData.yAxisData.ranges[i.index]);a=e.pop();r=e.shift();var o=i.data;var n=getDataPoints(o,a,r,x,f,l,s,c);h.beginPath();h.setStrokeStyle(i.color);h.setLineWidth(d.border*l.pix);h.setFillStyle(hexToRgb(i.color,d.opacity));n.forEach(function(t,e){h.moveTo(t.x+t.r,t.y);h.arc(t.x,t.y,t.r*l.pix,0,2*Math.PI,false)});h.closePath();h.fill();h.stroke();if(l.dataLabel!==false&&c===1){n.forEach(function(t,e){h.beginPath();var a=i.textSize*l.pix||s.fontSize;h.setFontSize(a);h.setFillStyle(i.textColor||"#FFFFFF");h.setTextAlign("center");h.fillText(String(t.t),t.x,t.y+a/2);h.closePath();h.stroke();h.setTextAlign("left")})}});h.restore();return{xAxisPoints:x,calPoints:i,eachSpacing:f}}function drawLineDataPoints(t,d,x,f){var p=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var u=assign({},{type:"straight",width:2,activeType:"none",linearType:"none",onShadow:false,animation:"vertical"},d.extra.line);u.width*=d.pix;let e=d.chartData.xAxisData,g=e.xAxisPoints,y=e.eachSpacing;var T=[];f.save();let v=0;let m=d.width+y;if(d._scrollDistance_&&d._scrollDistance_!==0&&d.enableScroll===true){f.translate(d._scrollDistance_,0);v=-d._scrollDistance_-y*2+d.area[3];m=v+(d.xAxis.itemCount+4)*y}t.forEach(function(e,c){f.beginPath();f.setStrokeStyle(e.color);f.moveTo(-1e4,-1e4);f.lineTo(-10001,-10001);f.stroke();let t,a,i;t=[].concat(d.chartData.yAxisData.ranges[e.index]);a=t.pop();i=t.shift();var r=e.data;var o=getLineDataPoints(r,a,i,g,y,d,x,u,p);T.push(o);var n=splitPoints(o,e);if(e.lineType=="dash"){let t=e.dashLength?e.dashLength:8;t*=d.pix;f.setLineDash([t,t])}f.beginPath();var l=e.color;if(u.linearType!=="none"&&e.linearColor&&e.linearColor.length>0){var s=f.createLinearGradient(d.chartData.xAxisData.startX,d.height/2,d.chartData.xAxisData.endX,d.height/2);for(var h=0;h0){f.setShadow(e.setShadow[0],e.setShadow[1],e.setShadow[2],e.setShadow[3])}else{f.setShadow(0,0,0,"rgba(0,0,0,0)")}f.setLineWidth(u.width);n.forEach(function(i,t){if(i.length===1){f.moveTo(i[0].x,i[0].y)}else{f.moveTo(i[0].x,i[0].y);let a=0;if(u.type==="curve"){for(let e=0;ev){f.moveTo(t.x,t.y);a=1}if(e>0&&t.x>v&&t.xv){f.moveTo(t.x,t.y);a=1}if(e>0&&t.x>v&&t.xv){f.moveTo(t.x,t.y);a=1}if(e>0&&t.x>v&&t.x4&&arguments[4]!==undefined?arguments[4]:1;let e=v.chartData.xAxisData,b=e.xAxisPoints,S=e.eachSpacing;let w=assign({},{width:S/2,barBorderCircle:false,barBorderRadius:[],seriesGap:2,linearType:"none",linearOpacity:1,customColor:[],colorStop:0},v.extra.mix.column);let A=assign({},{opacity:.2,gradient:false},v.extra.mix.area);let M=assign({},{width:2},v.extra.mix.line);let L=v.height-v.area[2];let F=[];var _=0;var k=0;t.forEach(function(t,e){if(t.type=="column"){k+=1}});T.save();let R=-2;let I=b.length+2;let P=0;let C=v.width+S;if(v._scrollDistance_&&v._scrollDistance_!==0&&v.enableScroll===true){T.translate(v._scrollDistance_,0);R=Math.floor(-v._scrollDistance_/S)-2;I=R+v.xAxis.itemCount+4;P=-v._scrollDistance_-S*2+v.area[3];C=P+(v.xAxis.itemCount+4)*S}w.customColor=fillCustomColor(w.linearType,w.customColor,t,m);t.forEach(function(n,t){let o,x,f;o=[].concat(v.chartData.yAxisData.ranges[n.index]);x=o.pop();f=o.shift();var p=n.data;var a=getDataPoints(p,x,f,b,S,v,m,D);F.push(a);if(n.type=="column"){a=fixColumeData(a,S,k,_,m,v);for(let t=0;tR&&tr?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;T.arc(h+t,c+t,t,-Math.PI,-Math.PI/2);T.arc(h+d-e,c+e,e,-Math.PI/2,0);T.arc(h+d-a,c+s-a,a,0,Math.PI/2);T.arc(h+i,c+s-i,i,Math.PI/2,Math.PI)}else{T.moveTo(l,o.y);T.lineTo(l+o.width,o.y);T.lineTo(l+o.width,v.height-v.area[2]);T.lineTo(l,v.height-v.area[2]);T.lineTo(l,o.y);T.setLineWidth(1);T.setStrokeStyle(u)}T.setFillStyle(e);T.closePath();T.fill()}}_+=1}if(n.type=="area"){let e=splitPoints(a,n);for(let t=0;t1){var r=i[0];let t=i[i.length-1];T.moveTo(r.x,r.y);let a=0;if(n.style==="curve"){for(let e=0;eP){T.moveTo(t.x,t.y);a=1}if(e>0&&t.x>P&&t.xP){T.moveTo(t.x,t.y);a=1}if(e>0&&t.x>P&&t.xP){T.moveTo(t.x,t.y);a=1}if(e>0&&t.x>P&&t.xP){T.moveTo(t.x,t.y);a=1}if(e>0&&t.x>P&&t.x1){if(h.extra.mount.widthRatio>2)h.extra.mount.widthRatio=2;l+=(h.extra.mount.widthRatio-1)*f}var s=n*n/l;var y=0;if(h._scrollDistance_){y=-h._scrollDistance_*n/l}d.beginPath();d.setLineCap("round");d.setLineWidth(6*h.pix);d.setStrokeStyle(h.xAxis.scrollBackgroundColor||"#EFEBEF");d.moveTo(t,o);d.lineTo(a,o);d.stroke();d.closePath();d.beginPath();d.setLineCap("round");d.setLineWidth(6*h.pix);d.setStrokeStyle(h.xAxis.scrollColor||"#A6A6A6");d.moveTo(t+y,o);d.lineTo(t+y+s,o);d.stroke();d.closePath();d.setLineCap("butt")}d.save();if(h._scrollDistance_&&h._scrollDistance_!==0){d.translate(h._scrollDistance_,0)}if(h.xAxis.calibration===true){d.setStrokeStyle(h.xAxis.gridColor||"#cccccc");d.setLineCap("butt");d.setLineWidth(1*h.pix);x.forEach(function(t,e){if(e>0){d.beginPath();d.moveTo(t-f/2,u);d.lineTo(t-f/2,u+3*h.pix);d.closePath();d.stroke()}})}if(h.xAxis.disableGrid!==true){d.setStrokeStyle(h.xAxis.gridColor||"#cccccc");d.setLineCap("butt");d.setLineWidth(1*h.pix);if(h.xAxis.gridType=="dash"){d.setLineDash([h.xAxis.dashLength*h.pix,h.xAxis.dashLength*h.pix])}h.xAxis.gridEval=h.xAxis.gridEval||1;x.forEach(function(t,e){if(e%h.xAxis.gridEval==0){d.beginPath();d.moveTo(t,u);d.lineTo(t,i);d.stroke()}});d.setLineDash([])}if(h.xAxis.disabled!==true){let t=r.length;if(h.xAxis.labelCount){if(h.xAxis.itemCount){t=Math.ceil(r.length/h.xAxis.itemCount*h.xAxis.labelCount)}else{t=h.xAxis.labelCount}t-=1}let e=Math.ceil(r.length/t);let a=[];let i=r.length;for(let t=0;t=h.area[3]-1&&n-Math.abs(o)<=h.width-h.area[1]+1){d.beginPath();d.setFontSize(g);d.setFillStyle(h.xAxis.fontColor||h.fontColor);d.fillText(String(a),x[e]+i,u+h.xAxis.marginTop*h.pix+(h.xAxis.lineHeight-h.xAxis.fontSize)*h.pix/2+h.xAxis.fontSize*h.pix);d.closePath();d.stroke()}})}else{a.forEach(function(t,e){var a=h.xAxis.formatter?h.xAxis.formatter(t):t;var i=h._scrollDistance_||0;var r=p=="center"?x[e]+f/2:x[e];if(r-Math.abs(i)>=h.area[3]-1&&r-Math.abs(i)<=h.width-h.area[1]+1){d.save();d.beginPath();d.setFontSize(g);d.setFillStyle(h.xAxis.fontColor||h.fontColor);var o=measureText(String(a),g,d);var n=x[e];if(p=="center"){n=x[e]+f/2}var l=0;if(h.xAxis.scrollShow){l=6*h.pix}var s=u+h.xAxis.marginTop*h.pix+g-g*Math.abs(Math.sin(c._xAxisTextAngle_));if(h.xAxis.rotateAngle<0){n-=g/2;o=0}else{n+=g/2;o=-o}d.translate(n,s);d.rotate(-1*c._xAxisTextAngle_);d.fillText(String(a),o,0);d.closePath();d.stroke();d.restore()}})}}d.restore();if(h.xAxis.title){d.beginPath();d.setFontSize(h.xAxis.titleFontSize*h.pix);d.setFillStyle(h.xAxis.titleFontColor);d.fillText(String(h.xAxis.title),h.width-h.area[1]+h.xAxis.titleOffsetX*h.pix,h.height-h.area[2]+h.xAxis.marginTop*h.pix+(h.xAxis.lineHeight-h.xAxis.titleFontSize)*h.pix/2+(h.xAxis.titleFontSize+h.xAxis.titleOffsetY)*h.pix);d.closePath();d.stroke()}if(h.xAxis.axisLine){d.beginPath();d.setStrokeStyle(h.xAxis.axisLineColor);d.setLineWidth(1*h.pix);d.moveTo(t,h.height-h.area[2]);d.lineTo(a,h.height-h.area[2]);d.stroke()}}function drawYAxisGrid(c,e,d,a){if(e.yAxis.disableGrid===true){return}let t=e.height-e.area[0]-e.area[2];let i=t/e.yAxis.splitNumber;let r=e.area[3];let o=e.chartData.xAxisData.xAxisPoints,n=e.chartData.xAxisData.eachSpacing;let l=n*(o.length-1);if(e.type=="mount"&&e.extra&&e.extra.mount&&e.extra.mount.widthRatio&&e.extra.mount.widthRatio>1){if(e.extra.mount.widthRatio>2)e.extra.mount.widthRatio=2;l+=(e.extra.mount.widthRatio-1)*n}let x=r+l;let s=[];let h=1;if(e.xAxis.axisLine===false){h=0}for(let t=h;t4&&arguments[4]!==undefined?arguments[4]:1;var n=assign({},{activeOpacity:.5,activeRadius:10,offsetAngle:0,labelWidth:15,ringWidth:30,customRadius:0,border:false,borderWidth:2,borderColor:"#FFFFFF",centerColor:"#FFFFFF",linearType:"none",customColor:[]},r.type=="pie"?r.extra.pie:r.extra.ring);var l={x:r.area[3]+(r.width-r.area[1]-r.area[3])/2,y:r.area[0]+(r.height-r.area[0]-r.area[2])/2};if(e.pieChartLinePadding==0){e.pieChartLinePadding=n.activeRadius*r.pix}var i=Math.min((r.width-r.area[1]-r.area[3])/2-e.pieChartLinePadding-e.pieChartTextPadding-e._pieTextMaxLength_,(r.height-r.area[0]-r.area[2])/2-e.pieChartLinePadding-e.pieChartTextPadding);i=i<10?10:i;if(n.customRadius>0){i=n.customRadius*r.pix}t=getPieDataPoints(t,i,a);var h=n.activeRadius*r.pix;n.customColor=fillCustomColor(n.linearType,n.customColor,t,e);t=t.map(function(t){t._start_+=n.offsetAngle*Math.PI/180;return t});t.forEach(function(t,e){if(r.tooltip){if(r.tooltip.index==e){o.beginPath();o.setFillStyle(hexToRgb(t.color,n.activeOpacity||.5));o.moveTo(l.x,l.y);o.arc(l.x,l.y,t._radius_+h,t._start_,t._start_+2*t._proportion_*Math.PI);o.closePath();o.fill()}}o.beginPath();o.setLineWidth(n.borderWidth*r.pix);o.lineJoin="round";o.setStrokeStyle(n.borderColor);var a=t.color;if(n.linearType=="custom"){var i;if(o.createCircularGradient){i=o.createCircularGradient(l.x,l.y,t._radius_)}else{i=o.createRadialGradient(l.x,l.y,0,l.x,l.y,t._radius_)}i.addColorStop(0,hexToRgb(n.customColor[t.linearIndex],1));i.addColorStop(1,hexToRgb(t.color,1));a=i}o.setFillStyle(a);o.moveTo(l.x,l.y);o.arc(l.x,l.y,t._radius_,t._start_,t._start_+2*t._proportion_*Math.PI);o.closePath();o.fill();if(n.border==true){o.stroke()}});if(r.type==="ring"){var s=i*.6;if(typeof n.ringWidth==="number"&&n.ringWidth>0){s=Math.max(0,i-n.ringWidth*r.pix)}o.beginPath();o.setFillStyle(n.centerColor);o.moveTo(l.x,l.y);o.arc(l.x,l.y,s,0,2*Math.PI);o.closePath();o.fill()}if(r.dataLabel!==false&&a===1){drawPieText(t,r,e,o,i,l)}if(a===1&&r.type==="ring"){drawRingTitle(r,e,o,l)}return{center:l,radius:i,series:t}}function drawRoseDataPoints(t,r,e,o){var a=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var n=assign({},{type:"area",activeOpacity:.5,activeRadius:10,offsetAngle:0,labelWidth:15,border:false,borderWidth:2,borderColor:"#FFFFFF",linearType:"none",customColor:[]},r.extra.rose);if(e.pieChartLinePadding==0){e.pieChartLinePadding=n.activeRadius*r.pix}var l={x:r.area[3]+(r.width-r.area[1]-r.area[3])/2,y:r.area[0]+(r.height-r.area[0]-r.area[2])/2};var i=Math.min((r.width-r.area[1]-r.area[3])/2-e.pieChartLinePadding-e.pieChartTextPadding-e._pieTextMaxLength_,(r.height-r.area[0]-r.area[2])/2-e.pieChartLinePadding-e.pieChartTextPadding);i=i<10?10:i;var s=n.minRadius||i*.5;if(i4&&arguments[4]!==undefined?arguments[4]:1;var o=assign({},{startAngle:.75,endAngle:.25,type:"default",direction:"cw",lineCap:"round",width:12,gap:2,linearType:"none",customColor:[]},i.extra.arcbar);a=getArcbarDataPoints(a,o,e);var n;if(o.centerX||o.centerY){n={x:o.centerX?o.centerX:i.width/2,y:o.centerY?o.centerY:i.height/2}}else{n={x:i.width/2,y:i.height/2}}var l;if(o.radius){l=o.radius}else{l=Math.min(n.x,n.y);l-=5*i.pix;l-=o.width/2}l=l<10?10:l;o.customColor=fillCustomColor(o.linearType,o.customColor,a,t);for(let e=0;e5&&arguments[5]!==undefined?arguments[5]:1;var f=assign({},{type:"default",startAngle:.75,endAngle:.25,width:15,labelOffset:13,splitLine:{fixRadius:0,splitNumber:10,width:15,color:"#FFFFFF",childNumber:5,childWidth:5},pointer:{width:15,color:"auto"}},c.extra.gauge);if(f.oldAngle==undefined){f.oldAngle=f.startAngle}if(f.oldData==undefined){f.oldData=0}n=getGaugeAxisPoints(n,f.startAngle,f.endAngle);var p={x:c.width/2,y:c.height/2};var u=Math.min(p.x,p.y);u-=5*c.pix;u-=f.width/2;u=u<10?10:u;var g=u-f.width;var y=0;if(f.type=="progress"){var v=u-f.width*3;d.beginPath();let t=d.createLinearGradient(p.x,p.y-v,p.x,p.y+v);t.addColorStop("0",hexToRgb(h[0].color,.3));t.addColorStop("1.0",hexToRgb("#FFFFFF",.1));d.setFillStyle(t);d.arc(p.x,p.y,v,0,2*Math.PI,false);d.fill();d.setLineWidth(f.width);d.setStrokeStyle(hexToRgb(h[0].color,.3));d.setLineCap("round");d.beginPath();d.arc(p.x,p.y,g,f.startAngle*Math.PI,f.endAngle*Math.PI,false);d.stroke();if(f.endAnglet/o){d.setStrokeStyle(hexToRgb(h[0].color,1))}else{d.setStrokeStyle(hexToRgb(h[0].color,.3))}d.setLineWidth(3*c.pix);d.moveTo(i,0);d.lineTo(r,0);d.stroke();d.rotate(a*Math.PI)}d.restore();h=getGaugeArcbarDataPoints(h,f,x);d.setLineWidth(f.width);d.setStrokeStyle(h[0].color);d.setLineCap("round");d.beginPath();d.arc(p.x,p.y,g,f.startAngle*Math.PI,h[0]._proportion_*Math.PI,false);d.stroke();let l=u-f.width*2.5;d.save();d.translate(p.x,p.y);d.rotate((h[0]._proportion_-1)*Math.PI);d.beginPath();d.setLineWidth(f.width/3);let s=d.createLinearGradient(0,-l*.6,0,l*.6);s.addColorStop("0",hexToRgb("#FFFFFF",0));s.addColorStop("0.5",hexToRgb(h[0].color,1));s.addColorStop("1.0",hexToRgb("#FFFFFF",0));d.setStrokeStyle(s);d.arc(0,0,l,.85*Math.PI,1.15*Math.PI,false);d.stroke();d.beginPath();d.setLineWidth(1);d.setStrokeStyle(h[0].color);d.setFillStyle(h[0].color);d.moveTo(-l-f.width/3/2,-4);d.lineTo(-l-f.width/3/2-4,0);d.lineTo(-l-f.width/3/2,4);d.lineTo(-l-f.width/3/2,-4);d.stroke();d.fill();d.restore()}else{d.setLineWidth(f.width);d.setLineCap("butt");for(let e=0;e4&&arguments[4]!==undefined?arguments[4]:1;var s=assign({},{gridColor:"#cccccc",gridType:"radar",gridEval:1,axisLabel:false,axisLabelTofix:0,labelShow:true,labelColor:"#666666",labelPointShow:false,labelPointRadius:3,labelPointColor:"#cccccc",opacity:.2,gridCount:3,border:false,borderWidth:2,linearType:"none",customColor:[]},n.extra.radar);var a=getRadarCoordinateSeries(n.categories.length);var h={x:n.area[3]+(n.width-n.area[1]-n.area[3])/2,y:n.area[0]+(n.height-n.area[0]-n.area[2])/2};var r=(n.width-n.area[1]-n.area[3])/2;var d=(n.height-n.area[0]-n.area[2])/2;var c=Math.min(r-(getMaxTextListLength(n.categories,i.fontSize,l)+i.radarLabelTextMargin),d-i.radarLabelTextMargin);c-=i.radarLabelTextMargin*n.pix;c=c<10?10:c;c=s.radius?s.radius:c;l.beginPath();l.setLineWidth(1*n.pix);l.setStrokeStyle(s.gridColor);a.forEach(function(t,e){var a=convertCoordinateOrigin(c*Math.cos(t),c*Math.sin(t),h);l.moveTo(h.x,h.y);if(e%s.gridEval==0){l.lineTo(a.x,a.y)}});l.stroke();l.closePath();var x=function t(i){var r={};l.beginPath();l.setLineWidth(1*n.pix);l.setStrokeStyle(s.gridColor);if(s.gridType=="radar"){a.forEach(function(t,e){var a=convertCoordinateOrigin(c/s.gridCount*i*Math.cos(t),c/s.gridCount*i*Math.sin(t),h);if(e===0){r=a;l.moveTo(a.x,a.y)}else{l.lineTo(a.x,a.y)}});l.lineTo(r.x,r.y)}else{var e=convertCoordinateOrigin(c/s.gridCount*i*Math.cos(1.5),c/s.gridCount*i*Math.sin(1.5),h);l.arc(h.x,h.y,h.y-e.y,0,2*Math.PI,false)}l.stroke();l.closePath()};for(var e=1;e<=s.gridCount;e++){x(e)}s.customColor=fillCustomColor(s.linearType,s.customColor,o,i);var f=getRadarDataPoints(a,h,c,o,n,t);f.forEach(function(t,e){l.beginPath();l.setLineWidth(s.borderWidth*n.pix);l.setStrokeStyle(t.color);var a=hexToRgb(t.color,s.opacity);if(s.linearType=="custom"){var i;if(l.createCircularGradient){i=l.createCircularGradient(h.x,h.y,c)}else{i=l.createRadialGradient(h.x,h.y,0,h.x,h.y,c)}i.addColorStop(0,hexToRgb(s.customColor[o[e].linearIndex],s.opacity));i.addColorStop(1,hexToRgb(t.color,s.opacity));a=i}l.setFillStyle(a);t.data.forEach(function(t,e){if(e===0){l.moveTo(t.position.x,t.position.y)}else{l.lineTo(t.position.x,t.position.y)}});l.closePath();l.fill();if(s.border===true){l.stroke()}l.closePath();if(n.dataPointShape!==false){var r=t.data.map(function(t){return t.position});drawPointShape(r,t.color,t.pointShape,l,n)}});if(s.axisLabel===true){const p=Math.max(s.max,Math.max.apply(null,dataCombine(o)));const u=c/s.gridCount;const g=n.fontSize*n.pix;l.setFontSize(g);l.setFillStyle(n.fontColor);l.setTextAlign("left");for(var e=0;eh.x?e.xMax:h.x;e.yMin=e.yMinh.y?e.yMax:h.y}}}return e}function coordinateToPoint(t,e,a,i,r,o){return{x:(e-a.xMin)*i+r,y:(a.yMax-t)*i+o}}function pointToCoordinate(t,e,a,i,r,o){return{x:(e-r)/i+a.xMin,y:a.yMax-(t-o)/i}}function isRayIntersectsSegment(t,e,a){if(e[1]==a[1]){return false}if(e[1]>t[1]&&a[1]>t[1]){return false}if(e[1]t[1]){return false}if(a[1]==t[1]&&e[1]>t[1]){return false}if(e[0]a[t].area[2]||e[1]>a[t].area[3]||e[2]i||e[3]>r){o=true;break}else{o=false}}else{o=true;break}}}return o}function getWordCloudPoint(c,t,d){let x=c.series;switch(t){case"normal":for(let l=0;l.7){return true}else{return false}};for(let h=0;h4&&arguments[4]!==undefined?arguments[4]:1;let a=assign({},{type:"normal",autoColors:true},r.extra.word);if(!r.chartData.wordCloudData){r.chartData.wordCloudData=getWordCloudPoint(r,a.type,o)}o.beginPath();o.setFillStyle(r.background);o.rect(0,0,r.width,r.height);o.fill();o.save();let l=r.chartData.wordCloudData;o.translate(r.width/2,r.height/2);for(let i=0;i0){if(r.tooltip){if(r.tooltip.index==i){o.strokeText(t,(l[i].areav[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].areav[1]+5+e-r.height/2)*n)}else{o.fillText(t,(l[i].areav[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].areav[1]+5+e-r.height/2)*n)}}else{o.fillText(t,(l[i].areav[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].areav[1]+5+e-r.height/2)*n)}}}else{if(l[i].area[0]>0){if(r.tooltip){if(r.tooltip.index==i){o.strokeText(t,(l[i].area[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].area[1]+5+e-r.height/2)*n)}else{o.fillText(t,(l[i].area[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].area[1]+5+e-r.height/2)*n)}}else{o.fillText(t,(l[i].area[0]+5-r.width/2)*n-a*(1-n)/2,(l[i].area[1]+5+e-r.height/2)*n)}}}o.stroke();o.restore()}o.restore()}function drawFunnelDataPoints(t,e,c,a){let d=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let i=assign({},{type:"funnel",activeWidth:10,activeOpacity:.3,border:false,borderWidth:2,borderColor:"#FFFFFF",fillOpacity:1,minSize:0,labelAlign:"right",linearType:"none",customColor:[]},e.extra.funnel);let r=(e.height-e.area[0]-e.area[2])/t.length;let o={x:e.area[3]+(e.width-e.area[1]-e.area[3])/2,y:e.height-e.area[2]};let n=i.activeWidth*e.pix;let x=Math.min((e.width-e.area[1]-e.area[3])/2-n,(e.height-e.area[0]-e.area[2])/2-n);let l=getFunnelDataPoints(t,x,i,r,d);a.save();a.translate(o.x,o.y);i.customColor=fillCustomColor(i.linearType,i.customColor,t,c);if(i.type=="pyramid"){for(let t=0;t0){l.area[3]+=i[t].width+l.yAxis.padding*l.pix}else{l.area[3]+=i[t].width}a+=1}else if(i[t].position=="right"){if(e>0){l.area[1]+=i[t].width+l.yAxis.padding*l.pix}else{l.area[1]+=i[t].width}e+=1}}}else{n.yAxisWidth=i}l.chartData.yAxisData=f;if(l.categories&&l.categories.length&&l.type!=="radar"&&l.type!=="gauge"&&l.type!=="bar"){l.chartData.xAxisData=getXAxisPoints(l.categories,l,n);let t=calCategoriesData(l.categories,l,n,l.chartData.xAxisData.eachSpacing,s),e=t.xAxisHeight,a=t.angle;n.xAxisHeight=e;n._xAxisTextAngle_=a;l.area[2]+=e;l.chartData.categoriesData=t}else{if(l.type==="line"||l.type==="area"||l.type==="scatter"||l.type==="bubble"||l.type==="bar"){l.chartData.xAxisData=calXAxisData(c,l,n,s);d=l.chartData.xAxisData.rangesFormat;let t=calCategoriesData(d,l,n,l.chartData.xAxisData.eachSpacing,s),e=t.xAxisHeight,a=t.angle;n.xAxisHeight=e;n._xAxisTextAngle_=a;l.area[2]+=e;l.chartData.categoriesData=t}else{l.chartData.xAxisData={xAxisPoints:[]}}}if(l.enableScroll&&l.xAxis.scrollAlign=="right"&&l._scrollDistance_===undefined){let t=0,e=l.chartData.xAxisData.xAxisPoints,a=l.chartData.xAxisData.startX,i=l.chartData.xAxisData.endX,r=l.chartData.xAxisData.eachSpacing;let o=r*(e.length-1);let n=i-a;t=n-o;h.scrollOption.currentOffset=t;h.scrollOption.startTouchX=t;h.scrollOption.distance=0;h.scrollOption.lastMoveTime=0;l._scrollDistance_=t}if(t==="pie"||t==="ring"||t==="rose"){n._pieTextMaxLength_=l.dataLabel===false?0:getPieTextMaxLength(x,n,s,l)}switch(t){case"word":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function(t){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawWordCloudDataPoints(c,l,n,s,t);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"map":s.clearRect(0,0,l.width,l.height);drawMapDataPoints(c,l,n,s);setTimeout(()=>{this.uevent.trigger("renderComplete")},50);break;case"funnel":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function(t){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.funnelData=drawFunnelDataPoints(c,l,n,s,t);drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,t);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"line":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawLineDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"scatter":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawScatterDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"bubble":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawBubbleDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"mix":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawMixDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"column":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawColumnDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"mount":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawMountDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"bar":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawXAxis(d,l,n,s);var a=drawBarDataPoints(c,l,n,s,e),i=a.yAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.yAxisPoints=i;l.chartData.xAxisPoints=l.chartData.xAxisData.xAxisPoints;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"area":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawAreaDataPoints(c,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"ring":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.pieData=drawPieDataPoints(c,l,n,s,e);drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"pie":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.pieData=drawPieDataPoints(c,l,n,s,e);drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"rose":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.pieData=drawRoseDataPoints(c,l,n,s,e);drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"radar":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.radarData=drawRadarDataPoints(c,l,n,s,e);drawLegend(l.series,l,n,s,l.chartData);drawToolTipBridge(l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"arcbar":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.arcbarData=drawArcbarDataPoints(c,l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"gauge":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}l.chartData.gaugeData=drawGaugeDataPoints(d,c,l,n,s,e);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break;case"candle":this.animationInstance=new Animation({timing:l.timing,duration:e,onProcess:function t(e){s.clearRect(0,0,l.width,l.height);if(l.rotate){contextRotate(s,l)}drawYAxisGrid(d,l,n,s);drawXAxis(d,l,n,s);var a=drawCandleDataPoints(c,x,l,n,s,e),i=a.xAxisPoints,r=a.calPoints,o=a.eachSpacing;l.chartData.xAxisPoints=i;l.chartData.calPoints=r;l.chartData.eachSpacing=o;drawYAxis(c,l,n,s);if(l.enableMarkLine!==false&&e===1){drawMarkLine(l,n,s)}if(x){drawLegend(x,l,n,s,l.chartData)}else{drawLegend(l.series,l,n,s,l.chartData)}drawToolTipBridge(l,n,s,e,o,i);drawCanvas(l,s)},onAnimationFinish:function t(){h.uevent.trigger("renderComplete")}});break}}function uChartsEvent(){this.events={}}uChartsEvent.prototype.addEventListener=function(t,e){this.events[t]=this.events[t]||[];this.events[t].push(e)};uChartsEvent.prototype.delEventListener=function(t){this.events[t]=[]};uChartsEvent.prototype.trigger=function(){for(var t=arguments.length,e=Array(t),a=0;a0&&arguments[0]!==undefined?arguments[0]:{};this.opts=assign({},this.opts,t);this.opts.updateData=true;let c=t.scrollPosition||"current";switch(c){case"current":this.opts._scrollDistance_=this.scrollOption.currentOffset;break;case"left":this.opts._scrollDistance_=0;this.scrollOption={currentOffset:0,startTouchX:0,distance:0,lastMoveTime:0};break;case"right":let t=calYAxisData(this.opts.series,this.opts,this.config,this.context),e=t.yAxisWidth;this.config.yAxisWidth=e;let a=0;let i=getXAxisPoints(this.opts.categories,this.opts,this.config),r=i.xAxisPoints,o=i.startX,n=i.endX,l=i.eachSpacing;let s=l*(r.length-1);let h=n-o;a=h-s;this.scrollOption={currentOffset:a,startTouchX:a,distance:0,lastMoveTime:0};this.opts._scrollDistance_=a;break}drawCharts.call(this,this.opts.type,this.opts,this.config,this.context)};uCharts.prototype.zoom=function(){var t=arguments.length>0&&arguments[0]!==undefined?arguments[0]:this.opts.xAxis.itemCount;if(this.opts.enableScroll!==true){console.log("[uCharts] 请启用滚动条后使用");return}let e=Math.round(Math.abs(this.scrollOption.currentOffset)/this.opts.chartData.eachSpacing)+Math.round(this.opts.xAxis.itemCount/2);this.opts.animation=false;this.opts.xAxis.itemCount=t.itemCount;let a=calYAxisData(this.opts.series,this.opts,this.config,this.context),i=a.yAxisWidth;this.config.yAxisWidth=i;let r=0;let o=getXAxisPoints(this.opts.categories,this.opts,this.config),h=o.xAxisPoints,c=o.startX,d=o.endX,n=o.eachSpacing;let x=n*e;let l=d-c;let s=l-n*(h.length-1);r=l/2-x;if(r>0){r=0}if(r=this.opts.categories.length?this.opts.categories.length:r;this.opts.animation=false;this.opts.xAxis.itemCount=r;let o=0;let n=getXAxisPoints(this.opts.categories,this.opts,this.config),x=n.xAxisPoints,f=n.startX,p=n.endX,l=n.eachSpacing;let u=l*this.scrollOption.moveCurrent1;let g=p-f;let y=g-l*(x.length-1);o=-u+Math.min(i[0].x,i[1].x)-this.opts.area[3]-l;if(o>0){o=0}if(o1&&arguments[1]!==undefined?arguments[1]:{};var a=null;if(t.changedTouches){a=t.changedTouches[0]}else{a=t.mp.changedTouches[0]}if(a){var i=getTouches(a,this.opts,t);var r=this.getLegendDataIndex(t);if(r>=0){if(this.opts.type=="candle"){this.opts.seriesMA[r].show=!this.opts.seriesMA[r].show}else{this.opts.series[r].show=!this.opts.series[r].show}this.opts.animation=e.animation?true:false;this.opts._scrollDistance_=this.scrollOption.currentOffset;drawCharts.call(this,this.opts.type,this.opts,this.config,this.context)}}};uCharts.prototype.showToolTip=function(t){var e=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var c=null;if(t.changedTouches){c=t.changedTouches[0]}else{c=t.mp.changedTouches[0]}if(!c){console.log("[uCharts] 未获取到event坐标信息")}var a=getTouches(c,this.opts,t);var d=this.scrollOption.currentOffset;var i=assign({},this.opts,{_scrollDistance_:d,animation:false});if(this.opts.type==="line"||this.opts.type==="area"||this.opts.type==="column"||this.opts.type==="scatter"||this.opts.type==="bubble"){var r=this.getCurrentDataIndex(t);var o=e.index==undefined?r.index:e.index;if(o>-1||o.length>0){var n=getSeriesDataItem(this.opts.series,o,r.group);if(n.length!==0){var l=getToolTipData(n,this.opts,o,r.group,this.opts.categories,e),s=l.textList,h=l.offset;h.y=a.y;i.tooltip={textList:e.textList!==undefined?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o,group:r.group}}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="mount"){var o=e.index==undefined?this.getCurrentDataIndex(t).index:e.index;if(o>-1){var i=assign({},this.opts,{animation:false});var n=assign({},i._series_[o]);var s=[{text:e.formatter?e.formatter(n,undefined,o,i):n.name+": "+n.data,color:n.color,legendShape:this.opts.extra.tooltip.legendShape=="auto"?n.legendShape:this.opts.extra.tooltip.legendShape}];var h={x:i.chartData.calPoints[o].x,y:a.y};i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="bar"){var r=this.getCurrentDataIndex(t);var o=e.index==undefined?r.index:e.index;if(o>-1||o.length>0){var n=getSeriesDataItem(this.opts.series,o,r.group);if(n.length!==0){var l=getToolTipData(n,this.opts,o,r.group,this.opts.categories,e),s=l.textList,h=l.offset;h.x=a.x;i.tooltip={textList:e.textList!==undefined?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="mix"){var r=this.getCurrentDataIndex(t);var o=e.index==undefined?r.index:e.index;if(o>-1){var d=this.scrollOption.currentOffset;var i=assign({},this.opts,{_scrollDistance_:d,animation:false});var n=getSeriesDataItem(this.opts.series,o);if(n.length!==0){var x=getMixToolTipData(n,this.opts,o,this.opts.categories,e),s=x.textList,h=x.offset;h.y=a.y;i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="candle"){var r=this.getCurrentDataIndex(t);var o=e.index==undefined?r.index:e.index;if(o>-1){var d=this.scrollOption.currentOffset;var i=assign({},this.opts,{_scrollDistance_:d,animation:false});var n=getSeriesDataItem(this.opts.series,o);if(n.length!==0){var l=getCandleToolTipData(this.opts.series[0].data,n,this.opts,o,this.opts.categories,this.opts.extra.candle,e),s=l.textList,h=l.offset;h.y=a.y;i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="pie"||this.opts.type==="ring"||this.opts.type==="rose"||this.opts.type==="funnel"){var o=e.index==undefined?this.getCurrentDataIndex(t):e.index;if(o>-1){var i=assign({},this.opts,{animation:false});var n=assign({},i._series_[o]);var s=[{text:e.formatter?e.formatter(n,undefined,o,i):n.name+": "+n.data,color:n.color,legendShape:this.opts.extra.tooltip.legendShape=="auto"?n.legendShape:this.opts.extra.tooltip.legendShape}];var h={x:a.x,y:a.y};i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="map"){var o=e.index==undefined?this.getCurrentDataIndex(t):e.index;if(o>-1){var i=assign({},this.opts,{animation:false});var n=assign({},this.opts.series[o]);n.name=n.properties.name;var s=[{text:e.formatter?e.formatter(n,undefined,o,this.opts):n.name,color:n.color,legendShape:this.opts.extra.tooltip.legendShape=="auto"?n.legendShape:this.opts.extra.tooltip.legendShape}];var h={x:a.x,y:a.y};i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}i.updateData=false;drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="word"){var o=e.index==undefined?this.getCurrentDataIndex(t):e.index;if(o>-1){var i=assign({},this.opts,{animation:false});var n=assign({},this.opts.series[o]);var s=[{text:e.formatter?e.formatter(n,undefined,o,this.opts):n.name,color:n.color,legendShape:this.opts.extra.tooltip.legendShape=="auto"?n.legendShape:this.opts.extra.tooltip.legendShape}];var h={x:a.x,y:a.y};i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}i.updateData=false;drawCharts.call(this,i.type,i,this.config,this.context)}if(this.opts.type==="radar"){var o=e.index==undefined?this.getCurrentDataIndex(t):e.index;if(o>-1){var i=assign({},this.opts,{animation:false});var n=getSeriesDataItem(this.opts.series,o);if(n.length!==0){var s=n.map(t=>{return{text:e.formatter?e.formatter(t,this.opts.categories[o],o,this.opts):t.name+": "+t.data,color:t.color,legendShape:this.opts.extra.tooltip.legendShape=="auto"?t.legendShape:this.opts.extra.tooltip.legendShape}});var h={x:a.x,y:a.y};i.tooltip={textList:e.textList?e.textList:s,offset:e.offset!==undefined?e.offset:h,option:e,index:o}}}drawCharts.call(this,i.type,i,this.config,this.context)}};uCharts.prototype.translate=function(t){this.scrollOption={currentOffset:t,startTouchX:t,distance:0,lastMoveTime:0};let e=assign({},this.opts,{_scrollDistance_:t,animation:false});drawCharts.call(this,this.opts.type,e,this.config,this.context)};uCharts.prototype.scrollStart=function(t){var e=null;if(t.changedTouches){e=t.changedTouches[0]}else{e=t.mp.changedTouches[0]}var a=getTouches(e,this.opts,t);if(e&&this.opts.enableScroll===true){this.scrollOption.startTouchX=a.x}};uCharts.prototype.scroll=function(t){if(this.scrollOption.lastMoveTime===0){this.scrollOption.lastMoveTime=Date.now()}let e=this.opts.touchMoveLimit||60;let a=Date.now();let i=a-this.scrollOption.lastMoveTime;if(i=0){var o="touchend"!==n?e.targetTouches[0]:e.changedTouches[0];o&&st(t,o,e,i)}else st(t,e,e,i),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var a=e.button;return null==e.which&&void 0!==a&&gw.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function ht(t,e,i){pw?t.addEventListener(e,i):t.attachEvent("on"+e,i)}function ct(t,e,i){pw?t.removeEventListener(e,i):t.detachEvent("on"+e,i)}function dt(t){return 2===t.which||3===t.which}function ft(t){var e=t[1][0]-t[0][0],i=t[1][1]-t[0][1];return Math.sqrt(e*e+i*i)}function pt(t){return[(t[0][0]+t[1][0])/2,(t[0][1]+t[1][1])/2]}function gt(t,e,i){return{type:t,event:i,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:i.zrX,offsetY:i.zrY,gestureEvent:i.gestureEvent,pinchX:i.pinchX,pinchY:i.pinchY,pinchScale:i.pinchScale,wheelDelta:i.zrDelta,zrByTouch:i.zrByTouch,which:i.which,stop:mt}}function mt(t){mw(this.event)}function vt(){}function yt(t,e,i){if(t[t.rectHover?"rectContain":"contain"](e,i)){for(var n,o=t;o;){if(o.clipPath&&!o.clipPath.contain(e,i))return!1;o.silent&&(n=!0),o=o.parent}return!n||xw}return!1}function xt(){var t=new bw(6);return _t(t),t}function _t(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function wt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t}function bt(t,e,i){var n=e[0]*i[0]+e[2]*i[1],o=e[1]*i[0]+e[3]*i[1],a=e[0]*i[2]+e[2]*i[3],r=e[1]*i[2]+e[3]*i[3],s=e[0]*i[4]+e[2]*i[5]+e[4],l=e[1]*i[4]+e[3]*i[5]+e[5];return t[0]=n,t[1]=o,t[2]=a,t[3]=r,t[4]=s,t[5]=l,t}function St(t,e,i){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4]+i[0],t[5]=e[5]+i[1],t}function Mt(t,e,i){var n=e[0],o=e[2],a=e[4],r=e[1],s=e[3],l=e[5],u=Math.sin(i),h=Math.cos(i);return t[0]=n*h+r*u,t[1]=-n*u+r*h,t[2]=o*h+s*u,t[3]=-o*u+h*s,t[4]=h*a+u*l,t[5]=h*l-u*a,t}function It(t,e,i){var n=i[0],o=i[1];return t[0]=e[0]*n,t[1]=e[1]*o,t[2]=e[2]*n,t[3]=e[3]*o,t[4]=e[4]*n,t[5]=e[5]*o,t}function Tt(t,e){var i=e[0],n=e[2],o=e[4],a=e[1],r=e[3],s=e[5],l=i*r-a*n;return l?(l=1/l,t[0]=r*l,t[1]=-a*l,t[2]=-n*l,t[3]=i*l,t[4]=(n*s-r*o)*l,t[5]=(a*o-i*s)*l,t):null}function At(t){var e=xt();return wt(e,t),e}function Dt(t){return t>Iw||t<-Iw}function Ct(t){this._target=t.target,this._life=t.life||1e3,this._delay=t.delay||0,this._initialized=!1,this.loop=null!=t.loop&&t.loop,this.gap=t.gap||0,this.easing=t.easing||"Linear",this.onframe=t.onframe,this.ondestroy=t.ondestroy,this.onrestart=t.onrestart,this._pausedTime=0,this._paused=!1}function Lt(t){return(t=Math.round(t))<0?0:t>255?255:t}function kt(t){return(t=Math.round(t))<0?0:t>360?360:t}function Pt(t){return t<0?0:t>1?1:t}function Nt(t){return Lt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100*255:parseInt(t,10))}function Ot(t){return Pt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100:parseFloat(t))}function Et(t,e,i){return i<0?i+=1:i>1&&(i-=1),6*i<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}function Rt(t,e,i){return t+(e-t)*i}function zt(t,e,i,n,o){return t[0]=e,t[1]=i,t[2]=n,t[3]=o,t}function Bt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}function Vt(t,e){Vw&&Bt(Vw,e),Vw=Bw.put(t,Vw||e.slice())}function Gt(t,e){if(t){e=e||[];var i=Bw.get(t);if(i)return Bt(e,i);var n=(t+="").replace(/ /g,"").toLowerCase();if(n in zw)return Bt(e,zw[n]),Vt(t,e),e;if("#"!==n.charAt(0)){var o=n.indexOf("("),a=n.indexOf(")");if(-1!==o&&a+1===n.length){var r=n.substr(0,o),s=n.substr(o+1,a-(o+1)).split(","),l=1;switch(r){case"rgba":if(4!==s.length)return void zt(e,0,0,0,1);l=Ot(s.pop());case"rgb":return 3!==s.length?void zt(e,0,0,0,1):(zt(e,Nt(s[0]),Nt(s[1]),Nt(s[2]),l),Vt(t,e),e);case"hsla":return 4!==s.length?void zt(e,0,0,0,1):(s[3]=Ot(s[3]),Ft(s,e),Vt(t,e),e);case"hsl":return 3!==s.length?void zt(e,0,0,0,1):(Ft(s,e),Vt(t,e),e);default:return}}zt(e,0,0,0,1)}else{if(4===n.length)return(u=parseInt(n.substr(1),16))>=0&&u<=4095?(zt(e,(3840&u)>>4|(3840&u)>>8,240&u|(240&u)>>4,15&u|(15&u)<<4,1),Vt(t,e),e):void zt(e,0,0,0,1);if(7===n.length){var u=parseInt(n.substr(1),16);return u>=0&&u<=16777215?(zt(e,(16711680&u)>>16,(65280&u)>>8,255&u,1),Vt(t,e),e):void zt(e,0,0,0,1)}}}}function Ft(t,e){var i=(parseFloat(t[0])%360+360)%360/360,n=Ot(t[1]),o=Ot(t[2]),a=o<=.5?o*(n+1):o+n-o*n,r=2*o-a;return e=e||[],zt(e,Lt(255*Et(r,a,i+1/3)),Lt(255*Et(r,a,i)),Lt(255*Et(r,a,i-1/3)),1),4===t.length&&(e[3]=t[3]),e}function Wt(t){if(t){var e,i,n=t[0]/255,o=t[1]/255,a=t[2]/255,r=Math.min(n,o,a),s=Math.max(n,o,a),l=s-r,u=(s+r)/2;if(0===l)e=0,i=0;else{i=u<.5?l/(s+r):l/(2-s-r);var h=((s-n)/6+l/2)/l,c=((s-o)/6+l/2)/l,d=((s-a)/6+l/2)/l;n===s?e=d-c:o===s?e=1/3+h-d:a===s&&(e=2/3+c-h),e<0&&(e+=1),e>1&&(e-=1)}var f=[360*e,i,u];return null!=t[3]&&f.push(t[3]),f}}function Ht(t,e){var i=Gt(t);if(i){for(var n=0;n<3;n++)i[n]=e<0?i[n]*(1-e)|0:(255-i[n])*e+i[n]|0,i[n]>255?i[n]=255:t[n]<0&&(i[n]=0);return qt(i,4===i.length?"rgba":"rgb")}}function Zt(t){var e=Gt(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Ut(t,e,i){if(e&&e.length&&t>=0&&t<=1){i=i||[];var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=e[o],s=e[a],l=n-o;return i[0]=Lt(Rt(r[0],s[0],l)),i[1]=Lt(Rt(r[1],s[1],l)),i[2]=Lt(Rt(r[2],s[2],l)),i[3]=Pt(Rt(r[3],s[3],l)),i}}function Xt(t,e,i){if(e&&e.length&&t>=0&&t<=1){var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=Gt(e[o]),s=Gt(e[a]),l=n-o,u=qt([Lt(Rt(r[0],s[0],l)),Lt(Rt(r[1],s[1],l)),Lt(Rt(r[2],s[2],l)),Pt(Rt(r[3],s[3],l))],"rgba");return i?{color:u,leftIndex:o,rightIndex:a,value:n}:u}}function jt(t,e,i,n){if(t=Gt(t))return t=Wt(t),null!=e&&(t[0]=kt(e)),null!=i&&(t[1]=Ot(i)),null!=n&&(t[2]=Ot(n)),qt(Ft(t),"rgba")}function Yt(t,e){if((t=Gt(t))&&null!=e)return t[3]=Pt(e),qt(t,"rgba")}function qt(t,e){if(t&&t.length){var i=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(i+=","+t[3]),e+"("+i+")"}}function Kt(t,e){return t[e]}function $t(t,e,i){t[e]=i}function Jt(t,e,i){return(e-t)*i+t}function Qt(t,e,i){return i>.5?e:t}function te(t,e,i,n,o){var a=t.length;if(1===o)for(s=0;so)t.length=o;else for(r=n;r=0&&!(m[i]<=e);i--);i=Math.min(i,u-2)}else{for(i=L;ie);i++);i=Math.min(i-1,u-2)}L=i,k=e;var n=m[i+1]-m[i];if(0!==n)if(I=(e-m[i])/n,l)if(A=v[i],T=v[0===i?i:i-1],D=v[i>u-2?u-1:i+1],C=v[i>u-3?u-1:i+2],d)ne(T,A,D,C,I,I*I,I*I*I,r(t,o),g);else{if(f)a=ne(T,A,D,C,I,I*I,I*I*I,P,1),a=re(P);else{if(p)return Qt(A,D,I);a=oe(T,A,D,C,I,I*I,I*I*I)}s(t,o,a)}else if(d)te(v[i],v[i+1],I,r(t,o),g);else{var a;if(f)te(v[i],v[i+1],I,P,1),a=re(P);else{if(p)return Qt(v[i],v[i+1],I);a=Jt(v[i],v[i+1],I)}s(t,o,a)}},ondestroy:i});return e&&"spline"!==e&&(N.easing=e),N}}}function ue(t,e,i,n,o,a,r,s){_(n)?(a=o,o=n,n=0):x(o)?(a=o,o="linear",n=0):x(n)?(a=n,n=0):x(i)?(a=i,i=500):i||(i=500),t.stopAnimation(),he(t,"",t,e,i,n,s);var l=t.animators.slice(),u=l.length;u||a&&a();for(var h=0;h0&&t.animate(e,!1).when(null==o?500:o,s).delay(a||0)}function ce(t,e,i,n){if(e){var o={};o[e]={},o[e][i]=n,t.attr(o)}else t.attr(i,n)}function de(t,e,i,n){i<0&&(t+=i,i=-i),n<0&&(e+=n,n=-n),this.x=t,this.y=e,this.width=i,this.height=n}function fe(t){for(var e=0;t>=eb;)e|=1&t,t>>=1;return t+e}function pe(t,e,i,n){var o=e+1;if(o===i)return 1;if(n(t[o++],t[e])<0){for(;o=0;)o++;return o-e}function ge(t,e,i){for(i--;e>>1])<0?l=a:s=a+1;var u=n-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;u>0;)t[s+u]=t[s+u-1],u--}t[s]=r}}function ve(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])>0){for(s=n-o;l0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}else{for(s=o+1;ls&&(l=s);var u=r;r=o-l,l=o-u}for(r++;r>>1);a(t,e[i+h])>0?r=h+1:l=h}return l}function ye(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])<0){for(s=o+1;ls&&(l=s);var u=r;r=o-l,l=o-u}else{for(s=n-o;l=0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}for(r++;r>>1);a(t,e[i+h])<0?l=h:r=h+1}return l}function xe(t,e){function i(i){var s=a[i],u=r[i],h=a[i+1],c=r[i+1];r[i]=u+c,i===l-3&&(a[i+1]=a[i+2],r[i+1]=r[i+2]),l--;var d=ye(t[h],t,s,u,0,e);s+=d,0!==(u-=d)&&0!==(c=ve(t[s+u-1],t,h,c,c-1,e))&&(u<=c?n(s,u,h,c):o(s,u,h,c))}function n(i,n,o,a){var r=0;for(r=0;r=ib||f>=ib);if(p)break;g<0&&(g=0),g+=2}if((s=g)<1&&(s=1),1===n){for(r=0;r=0;r--)t[f+r]=t[d+r];if(0===n){v=!0;break}}if(t[c--]=u[h--],1==--a){v=!0;break}if(0!=(m=a-ve(t[l],u,0,a,a-1,e))){for(a-=m,f=(c-=m)+1,d=(h-=m)+1,r=0;r=ib||m>=ib);if(v)break;p<0&&(p=0),p+=2}if((s=p)<1&&(s=1),1===a){for(f=(c-=n)+1,d=(l-=n)+1,r=n-1;r>=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else{if(0===a)throw new Error;for(d=c-(a-1),r=0;r=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else for(d=c-(a-1),r=0;r1;){var t=l-2;if(t>=1&&r[t-1]<=r[t]+r[t+1]||t>=2&&r[t-2]<=r[t]+r[t-1])r[t-1]r[t+1])break;i(t)}},this.forceMergeRuns=function(){for(;l>1;){var t=l-2;t>0&&r[t-1]s&&(l=s),me(t,i,i+l,i+a,e),a=l}r.pushRun(i,a),r.mergeRuns(),o-=a,i+=a}while(0!==o);r.forceMergeRuns()}}function we(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}function be(t,e,i){var n=null==e.x?0:e.x,o=null==e.x2?1:e.x2,a=null==e.y?0:e.y,r=null==e.y2?0:e.y2;return e.global||(n=n*i.width+i.x,o=o*i.width+i.x,a=a*i.height+i.y,r=r*i.height+i.y),n=isNaN(n)?0:n,o=isNaN(o)?1:o,a=isNaN(a)?0:a,r=isNaN(r)?0:r,t.createLinearGradient(n,a,o,r)}function Se(t,e,i){var n=i.width,o=i.height,a=Math.min(n,o),r=null==e.x?.5:e.x,s=null==e.y?.5:e.y,l=null==e.r?.5:e.r;return e.global||(r=r*n+i.x,s=s*o+i.y,l*=a),t.createRadialGradient(r,s,0,r,s,l)}function Me(){return!1}function Ie(t,e,i){var n=iw(),o=e.getWidth(),a=e.getHeight(),r=n.style;return r&&(r.position="absolute",r.left=0,r.top=0,r.width=o+"px",r.height=a+"px",n.setAttribute("data-zr-dom-id",t)),n.width=o*i,n.height=a*i,n}function Te(t){if("string"==typeof t){var e=mb.get(t);return e&&e.image}return t}function Ae(t,e,i,n,o){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!i)return e;var a=mb.get(t),r={hostEl:i,cb:n,cbPayload:o};return a?!Ce(e=a.image)&&a.pending.push(r):((e=new Image).onload=e.onerror=De,mb.put(t,e.__cachedImgObj={image:e,pending:[r]}),e.src=e.__zrImageSrc=t),e}return t}return e}function De(){var t=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;exb&&(yb=0,vb={}),yb++,vb[i]=o,o}function ke(t,e,i,n,o,a,r,s){return r?Ne(t,e,i,n,o,a,r,s):Pe(t,e,i,n,o,a,s)}function Pe(t,e,i,n,o,a,r){var s=He(t,e,o,a,r),l=Le(t,e);o&&(l+=o[1]+o[3]);var u=s.outerHeight,h=new de(Oe(0,l,i),Ee(0,u,n),l,u);return h.lineHeight=s.lineHeight,h}function Ne(t,e,i,n,o,a,r,s){var l=Ze(t,{rich:r,truncate:s,font:e,textAlign:i,textPadding:o,textLineHeight:a}),u=l.outerWidth,h=l.outerHeight;return new de(Oe(0,u,i),Ee(0,h,n),u,h)}function Oe(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function Ee(t,e,i){return"middle"===i?t-=e/2:"bottom"===i&&(t-=e),t}function Re(t,e,i){var n=e.x,o=e.y,a=e.height,r=e.width,s=a/2,l="left",u="top";switch(t){case"left":n-=i,o+=s,l="right",u="middle";break;case"right":n+=i+r,o+=s,u="middle";break;case"top":n+=r/2,o-=i,l="center",u="bottom";break;case"bottom":n+=r/2,o+=a+i,l="center";break;case"inside":n+=r/2,o+=s,l="center",u="middle";break;case"insideLeft":n+=i,o+=s,u="middle";break;case"insideRight":n+=r-i,o+=s,l="right",u="middle";break;case"insideTop":n+=r/2,o+=i,l="center";break;case"insideBottom":n+=r/2,o+=a-i,l="center",u="bottom";break;case"insideTopLeft":n+=i,o+=i;break;case"insideTopRight":n+=r-i,o+=i,l="right";break;case"insideBottomLeft":n+=i,o+=a-i,u="bottom";break;case"insideBottomRight":n+=r-i,o+=a-i,l="right",u="bottom"}return{x:n,y:o,textAlign:l,textVerticalAlign:u}}function ze(t,e,i,n,o){if(!e)return"";var a=(t+"").split("\n");o=Be(e,i,n,o);for(var r=0,s=a.length;r=r;l++)s-=r;var u=Le(i,e);return u>s&&(i="",u=0),s=t-u,n.ellipsis=i,n.ellipsisWidth=u,n.contentWidth=s,n.containerWidth=t,n}function Ve(t,e){var i=e.containerWidth,n=e.font,o=e.contentWidth;if(!i)return"";var a=Le(t,n);if(a<=i)return t;for(var r=0;;r++){if(a<=o||r>=e.maxIterations){t+=e.ellipsis;break}var s=0===r?Ge(t,o,e.ascCharWidth,e.cnCharWidth):a>0?Math.floor(t.length*o/a):0;a=Le(t=t.substr(0,s),n)}return""===t&&(t=e.placeholder),t}function Ge(t,e,i,n){for(var o=0,a=0,r=t.length;au)t="",r=[];else if(null!=h)for(var c=Be(h-(i?i[1]+i[3]:0),e,o.ellipsis,{minChar:o.minChar,placeholder:o.placeholder}),d=0,f=r.length;do&&Ue(i,t.substring(o,a)),Ue(i,n[2],n[1]),o=_b.lastIndex}of)return{lines:[],width:0,height:0};k.textWidth=Le(k.text,_);var b=y.textWidth,S=null==b||"auto"===b;if("string"==typeof b&&"%"===b.charAt(b.length-1))k.percentWidth=b,u.push(k),b=0;else{if(S){b=k.textWidth;var M=y.textBackgroundColor,I=M&&M.image;I&&Ce(I=Te(I))&&(b=Math.max(b,I.width*w/I.height))}var T=x?x[1]+x[3]:0;b+=T;var C=null!=d?d-m:null;null!=C&&Cl&&(i*=l/(c=i+n),n*=l/c),o+a>l&&(o*=l/(c=o+a),a*=l/c),n+o>u&&(n*=u/(c=n+o),o*=u/c),i+a>u&&(i*=u/(c=i+a),a*=u/c),t.moveTo(r+i,s),t.lineTo(r+l-n,s),0!==n&&t.arc(r+l-n,s+n,n,-Math.PI/2,0),t.lineTo(r+l,s+u-o),0!==o&&t.arc(r+l-o,s+u-o,o,0,Math.PI/2),t.lineTo(r+a,s+u),0!==a&&t.arc(r+a,s+u-a,a,Math.PI/2,Math.PI),t.lineTo(r,s+i),0!==i&&t.arc(r+i,s+i,i,Math.PI,1.5*Math.PI)}function Ye(t){return qe(t),d(t.rich,qe),t}function qe(t){if(t){t.font=Xe(t);var e=t.textAlign;"middle"===e&&(e="center"),t.textAlign=null==e||Mb[e]?e:"left";var i=t.textVerticalAlign||t.textBaseline;"center"===i&&(i="middle"),t.textVerticalAlign=null==i||Ib[i]?i:"top",t.textPadding&&(t.textPadding=L(t.textPadding))}}function Ke(t,e,i,n,o,a){n.rich?Je(t,e,i,n,o,a):$e(t,e,i,n,o,a)}function $e(t,e,i,n,o,a){var r,s=ii(n),l=!1,u=e.__attrCachedBy===rb.PLAIN_TEXT;a!==sb?(a&&(r=a.style,l=!s&&u&&r),e.__attrCachedBy=s?rb.NONE:rb.PLAIN_TEXT):u&&(e.__attrCachedBy=rb.NONE);var h=n.font||Sb;l&&h===(r.font||Sb)||(e.font=h);var c=t.__computedFont;t.__styleFont!==h&&(t.__styleFont=h,c=t.__computedFont=e.font);var d=n.textPadding,f=n.textLineHeight,p=t.__textCotentBlock;p&&!t.__dirtyText||(p=t.__textCotentBlock=He(i,c,d,f,n.truncate));var g=p.outerHeight,m=p.lines,v=p.lineHeight,y=ai(g,n,o),x=y.baseX,_=y.baseY,w=y.textAlign||"left",b=y.textVerticalAlign;ti(e,n,o,x,_);var S=Ee(_,g,b),M=x,I=S;if(s||d){var T=Le(i,c);d&&(T+=d[1]+d[3]);var A=Oe(x,T,w);s&&ni(t,e,n,A,S,T,g),d&&(M=hi(x,w,d),I+=d[0])}e.textAlign=w,e.textBaseline="middle",e.globalAlpha=n.opacity||1;for(B=0;B=0&&"right"===(_=b[C]).textAlign;)ei(t,e,_,n,M,v,D,"right"),I-=_.width,D-=_.width,C--;for(A+=(a-(A-m)-(y-D)-I)/2;T<=C;)ei(t,e,_=b[T],n,M,v,A+_.width/2,"center"),A+=_.width,T++;v+=M}}function ti(t,e,i,n,o){if(i&&e.textRotation){var a=e.textOrigin;"center"===a?(n=i.width/2+i.x,o=i.height/2+i.y):a&&(n=a[0]+i.x,o=a[1]+i.y),t.translate(n,o),t.rotate(-e.textRotation),t.translate(-n,-o)}}function ei(t,e,i,n,o,a,r,s){var l=n.rich[i.styleName]||{};l.text=i.text;var u=i.textVerticalAlign,h=a+o/2;"top"===u?h=a+i.height/2:"bottom"===u&&(h=a+o-i.height/2),!i.isLineHolder&&ii(l)&&ni(t,e,l,"right"===s?r-i.width:"center"===s?r-i.width/2:r,h-i.height/2,i.width,i.height);var c=i.textPadding;c&&(r=hi(r,s,c),h-=i.height/2-c[2]-i.textHeight/2),ri(e,"shadowBlur",D(l.textShadowBlur,n.textShadowBlur,0)),ri(e,"shadowColor",l.textShadowColor||n.textShadowColor||"transparent"),ri(e,"shadowOffsetX",D(l.textShadowOffsetX,n.textShadowOffsetX,0)),ri(e,"shadowOffsetY",D(l.textShadowOffsetY,n.textShadowOffsetY,0)),ri(e,"textAlign",s),ri(e,"textBaseline","middle"),ri(e,"font",i.font||Sb);var d=si(l.textStroke||n.textStroke,p),f=li(l.textFill||n.textFill),p=A(l.textStrokeWidth,n.textStrokeWidth);d&&(ri(e,"lineWidth",p),ri(e,"strokeStyle",d),e.strokeText(i.text,r,h)),f&&(ri(e,"fillStyle",f),e.fillText(i.text,r,h))}function ii(t){return!!(t.textBackgroundColor||t.textBorderWidth&&t.textBorderColor)}function ni(t,e,i,n,o,a,r){var s=i.textBackgroundColor,l=i.textBorderWidth,u=i.textBorderColor,h=_(s);if(ri(e,"shadowBlur",i.textBoxShadowBlur||0),ri(e,"shadowColor",i.textBoxShadowColor||"transparent"),ri(e,"shadowOffsetX",i.textBoxShadowOffsetX||0),ri(e,"shadowOffsetY",i.textBoxShadowOffsetY||0),h||l&&u){e.beginPath();var c=i.textBorderRadius;c?je(e,{x:n,y:o,width:a,height:r,r:c}):e.rect(n,o,a,r),e.closePath()}if(h)if(ri(e,"fillStyle",s),null!=i.fillOpacity){f=e.globalAlpha;e.globalAlpha=i.fillOpacity*i.opacity,e.fill(),e.globalAlpha=f}else e.fill();else if(w(s)){var d=s.image;(d=Ae(d,null,t,oi,s))&&Ce(d)&&e.drawImage(d,n,o,a,r)}if(l&&u)if(ri(e,"lineWidth",l),ri(e,"strokeStyle",u),null!=i.strokeOpacity){var f=e.globalAlpha;e.globalAlpha=i.strokeOpacity*i.opacity,e.stroke(),e.globalAlpha=f}else e.stroke()}function oi(t,e){e.image=t}function ai(t,e,i){var n=e.x||0,o=e.y||0,a=e.textAlign,r=e.textVerticalAlign;if(i){var s=e.textPosition;if(s instanceof Array)n=i.x+ui(s[0],i.width),o=i.y+ui(s[1],i.height);else{var l=Re(s,i,e.textDistance);n=l.x,o=l.y,a=a||l.textAlign,r=r||l.textVerticalAlign}var u=e.textOffset;u&&(n+=u[0],o+=u[1])}return{baseX:n,baseY:o,textAlign:a,textVerticalAlign:r}}function ri(t,e,i){return t[e]=ab(t,e,i),t[e]}function si(t,e){return null==t||e<=0||"transparent"===t||"none"===t?null:t.image||t.colorStops?"#000":t}function li(t){return null==t||"none"===t?null:t.image||t.colorStops?"#000":t}function ui(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t}function hi(t,e,i){return"right"===e?t-i[1]:"center"===e?t+i[3]/2-i[1]/2:t+i[3]}function ci(t,e){return null!=t&&(t||e.textBackgroundColor||e.textBorderWidth&&e.textBorderColor||e.textPadding)}function di(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&"style"!==e&&(this[e]=t[e]);this.style=new ub(t.style,this),this._rect=null,this.__clipPaths=[]}function fi(t){di.call(this,t)}function pi(t){return parseInt(t,10)}function gi(t){return!!t&&(!!t.__builtin__||"function"==typeof t.resize&&"function"==typeof t.refresh)}function mi(t,e,i){return Cb.copy(t.getBoundingRect()),t.transform&&Cb.applyTransform(t.transform),Lb.width=e,Lb.height=i,!Cb.intersect(Lb)}function vi(t,e){if(t===e)return!1;if(!t||!e||t.length!==e.length)return!0;for(var i=0;i=i.length&&i.push({option:t})}}),i}function Ni(t){var e=R();Zb(t,function(t,i){var n=t.exist;n&&e.set(n.id,t)}),Zb(t,function(t,i){var n=t.option;k(!n||null==n.id||!e.get(n.id)||e.get(n.id)===t,"id duplicates: "+(n&&n.id)),n&&null!=n.id&&e.set(n.id,t),!t.keyInfo&&(t.keyInfo={})}),Zb(t,function(t,i){var n=t.exist,o=t.option,a=t.keyInfo;if(Ub(o)){if(a.name=null!=o.name?o.name+"":n?n.name:jb+i,n)a.id=n.id;else if(null!=o.id)a.id=o.id+"";else{var r=0;do{a.id="\0"+a.name+"\0"+r++}while(e.get(a.id))}e.set(a.id,t)}})}function Oi(t){var e=t.name;return!(!e||!e.indexOf(jb))}function Ei(t){return Ub(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Ri(t,e){function i(t,e,i){for(var n=0,o=t.length;n-rS&&trS||t<-rS}function tn(t,e,i,n,o){var a=1-o;return a*a*(a*t+3*o*e)+o*o*(o*n+3*a*i)}function en(t,e,i,n,o){var a=1-o;return 3*(((e-t)*a+2*(i-e)*o)*a+(n-i)*o*o)}function nn(t,e,i,n,o,a){var r=n+3*(e-i)-t,s=3*(i-2*e+t),l=3*(e-t),u=t-o,h=s*s-3*r*l,c=s*l-9*r*u,d=l*l-3*s*u,f=0;if(Ji(h)&&Ji(c))Ji(s)?a[0]=0:(M=-l/s)>=0&&M<=1&&(a[f++]=M);else{var p=c*c-4*h*d;if(Ji(p)){var g=c/h,m=-g/2;(M=-s/r+g)>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m)}else if(p>0){var v=aS(p),y=h*s+1.5*r*(-c+v),x=h*s+1.5*r*(-c-v);(M=(-s-((y=y<0?-oS(-y,uS):oS(y,uS))+(x=x<0?-oS(-x,uS):oS(x,uS))))/(3*r))>=0&&M<=1&&(a[f++]=M)}else{var _=(2*h*s-3*r*c)/(2*aS(h*h*h)),w=Math.acos(_)/3,b=aS(h),S=Math.cos(w),M=(-s-2*b*S)/(3*r),m=(-s+b*(S+lS*Math.sin(w)))/(3*r),I=(-s+b*(S-lS*Math.sin(w)))/(3*r);M>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m),I>=0&&I<=1&&(a[f++]=I)}}return f}function on(t,e,i,n,o){var a=6*i-12*e+6*t,r=9*e+3*n-3*t-9*i,s=3*e-3*t,l=0;if(Ji(r))Qi(a)&&(c=-s/a)>=0&&c<=1&&(o[l++]=c);else{var u=a*a-4*r*s;if(Ji(u))o[0]=-a/(2*r);else if(u>0){var h=aS(u),c=(-a+h)/(2*r),d=(-a-h)/(2*r);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function an(t,e,i,n,o,a){var r=(e-t)*o+t,s=(i-e)*o+e,l=(n-i)*o+i,u=(s-r)*o+r,h=(l-s)*o+s,c=(h-u)*o+u;a[0]=t,a[1]=r,a[2]=u,a[3]=c,a[4]=c,a[5]=h,a[6]=l,a[7]=n}function rn(t,e,i,n,o,a,r,s,l,u,h){var c,d,f,p,g,m=.005,v=1/0;hS[0]=l,hS[1]=u;for(var y=0;y<1;y+=.05)cS[0]=tn(t,i,o,r,y),cS[1]=tn(e,n,a,s,y),(p=hw(hS,cS))=0&&p=0&&c<=1&&(o[l++]=c);else{var u=r*r-4*a*s;if(Ji(u))(c=-r/(2*a))>=0&&c<=1&&(o[l++]=c);else if(u>0){var h=aS(u),c=(-r+h)/(2*a),d=(-r-h)/(2*a);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function hn(t,e,i){var n=t+i-2*e;return 0===n?.5:(t-e)/n}function cn(t,e,i,n,o){var a=(e-t)*n+t,r=(i-e)*n+e,s=(r-a)*n+a;o[0]=t,o[1]=a,o[2]=s,o[3]=s,o[4]=r,o[5]=i}function dn(t,e,i,n,o,a,r,s,l){var u,h=.005,c=1/0;hS[0]=r,hS[1]=s;for(var d=0;d<1;d+=.05)cS[0]=sn(t,i,o,d),cS[1]=sn(e,n,a,d),(m=hw(hS,cS))=0&&m1e-4)return s[0]=t-i,s[1]=e-n,l[0]=t+i,void(l[1]=e+n);if(yS[0]=mS(o)*i+t,yS[1]=gS(o)*n+e,xS[0]=mS(a)*i+t,xS[1]=gS(a)*n+e,u(s,yS,xS),h(l,yS,xS),(o%=vS)<0&&(o+=vS),(a%=vS)<0&&(a+=vS),o>a&&!r?a+=vS:oo&&(_S[0]=mS(f)*i+t,_S[1]=gS(f)*n+e,u(s,_S,s),h(l,_S,l))}function yn(t,e,i,n,o,a,r){if(0===o)return!1;var s=o,l=0,u=t;if(r>e+s&&r>n+s||rt+s&&a>i+s||ae+c&&h>n+c&&h>a+c&&h>s+c||ht+c&&u>i+c&&u>o+c&&u>r+c||ue+u&&l>n+u&&l>a+u||lt+u&&s>i+u&&s>o+u||si||h+uo&&(o+=zS);var d=Math.atan2(l,s);return d<0&&(d+=zS),d>=n&&d<=o||d+zS>=n&&d+zS<=o}function Sn(t,e,i,n,o,a){if(a>e&&a>n||ao?r:0}function Mn(t,e){return Math.abs(t-e)e&&u>n&&u>a&&u>s||u1&&In(),c=tn(e,n,a,s,WS[0]),p>1&&(d=tn(e,n,a,s,WS[1]))),2===p?me&&s>n&&s>a||s=0&&u<=1){for(var h=0,c=sn(e,n,a,u),d=0;di||s<-i)return 0;u=Math.sqrt(i*i-s*s);FS[0]=-u,FS[1]=u;var l=Math.abs(n-o);if(l<1e-4)return 0;if(l%VS<1e-4){n=0,o=VS;p=a?1:-1;return r>=FS[0]+t&&r<=FS[1]+t?p:0}if(a){var u=n;n=wn(o),o=wn(u)}else n=wn(n),o=wn(o);n>o&&(o+=VS);for(var h=0,c=0;c<2;c++){var d=FS[c];if(d+t>r){var f=Math.atan2(s,d),p=a?1:-1;f<0&&(f=VS+f),(f>=n&&f<=o||f+VS>=n&&f+VS<=o)&&(f>Math.PI/2&&f<1.5*Math.PI&&(p=-p),h+=p)}}return h}function Cn(t,e,i,n,o){for(var a=0,r=0,s=0,l=0,u=0,h=0;h1&&(i||(a+=Sn(r,s,l,u,n,o))),1===h&&(l=r=t[h],u=s=t[h+1]),c){case BS.M:r=l=t[h++],s=u=t[h++];break;case BS.L:if(i){if(yn(r,s,t[h],t[h+1],e,n,o))return!0}else a+=Sn(r,s,t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.C:if(i){if(xn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=Tn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.Q:if(i){if(_n(r,s,t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=An(r,s,t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.A:var d=t[h++],f=t[h++],p=t[h++],g=t[h++],m=t[h++],v=t[h++];h+=1;var y=1-t[h++],x=Math.cos(m)*p+d,_=Math.sin(m)*g+f;h>1?a+=Sn(r,s,x,_,n,o):(l=x,u=_);var w=(n-d)*g/p+d;if(i){if(bn(d,f,g,m,m+v,y,e,w,o))return!0}else a+=Dn(d,f,g,m,m+v,y,w,o);r=Math.cos(m+v)*p+d,s=Math.sin(m+v)*g+f;break;case BS.R:l=r=t[h++],u=s=t[h++];var x=l+t[h++],_=u+t[h++];if(i){if(yn(l,u,x,u,e,n,o)||yn(x,u,x,_,e,n,o)||yn(x,_,l,_,e,n,o)||yn(l,_,l,u,e,n,o))return!0}else a+=Sn(x,u,x,_,n,o),a+=Sn(l,_,l,u,n,o);break;case BS.Z:if(i){if(yn(r,s,l,u,e,n,o))return!0}else a+=Sn(r,s,l,u,n,o);r=l,s=u}}return i||Mn(s,u)||(a+=Sn(r,s,l,u,n,o)||0),0!==a}function Ln(t,e,i){return Cn(t,0,!1,e,i)}function kn(t,e,i,n){return Cn(t,e,!0,i,n)}function Pn(t){di.call(this,t),this.path=null}function Nn(t,e,i,n,o,a,r,s,l,u,h){var c=l*(tM/180),d=QS(c)*(t-i)/2+JS(c)*(e-n)/2,f=-1*JS(c)*(t-i)/2+QS(c)*(e-n)/2,p=d*d/(r*r)+f*f/(s*s);p>1&&(r*=$S(p),s*=$S(p));var g=(o===a?-1:1)*$S((r*r*(s*s)-r*r*(f*f)-s*s*(d*d))/(r*r*(f*f)+s*s*(d*d)))||0,m=g*r*f/s,v=g*-s*d/r,y=(t+i)/2+QS(c)*m-JS(c)*v,x=(e+n)/2+JS(c)*m+QS(c)*v,_=nM([1,0],[(d-m)/r,(f-v)/s]),w=[(d-m)/r,(f-v)/s],b=[(-1*d-m)/r,(-1*f-v)/s],S=nM(w,b);iM(w,b)<=-1&&(S=tM),iM(w,b)>=1&&(S=0),0===a&&S>0&&(S-=2*tM),1===a&&S<0&&(S+=2*tM),h.addData(u,y,x,r,s,_,S,c,a)}function On(t){if(!t)return new ES;for(var e,i=0,n=0,o=i,a=n,r=new ES,s=ES.CMD,l=t.match(oM),u=0;u=2){if(o&&"spline"!==o){var a=fM(n,o,i,e.smoothConstraint);t.moveTo(n[0][0],n[0][1]);for(var r=n.length,s=0;s<(i?r:r-1);s++){var l=a[2*s],u=a[2*s+1],h=n[(s+1)%r];t.bezierCurveTo(l[0],l[1],u[0],u[1],h[0],h[1])}}else{"spline"===o&&(n=dM(n,i)),t.moveTo(n[0][0],n[0][1]);for(var s=1,c=n.length;s=0)?(i={textFill:null,textStroke:t.textStroke,textStrokeWidth:t.textStrokeWidth},t.textFill="#fff",null==t.textStroke&&(t.textStroke=a,null==t.textStrokeWidth&&(t.textStrokeWidth=2))):null!=a&&(i={textFill:null},t.textFill=a),i&&(t.insideRollback=i)}}function bo(t){var e=t.insideRollback;e&&(t.textFill=e.textFill,t.textStroke=e.textStroke,t.textStrokeWidth=e.textStrokeWidth,t.insideRollback=null)}function So(t,e){var i=e||e.getModel("textStyle");return P([t.fontStyle||i&&i.getShallow("fontStyle")||"",t.fontWeight||i&&i.getShallow("fontWeight")||"",(t.fontSize||i&&i.getShallow("fontSize")||12)+"px",t.fontFamily||i&&i.getShallow("fontFamily")||"sans-serif"].join(" "))}function Mo(t,e,i,n,o,a){if("function"==typeof o&&(a=o,o=null),n&&n.isAnimationEnabled()){var r=t?"Update":"",s=n.getShallow("animationDuration"+r),l=n.getShallow("animationEasing"+r),u=n.getShallow("animationDelay"+r);"function"==typeof u&&(u=u(o,n.getAnimationDelayParams?n.getAnimationDelayParams(e,o):null)),"function"==typeof s&&(s=s(o)),s>0?e.animateTo(i,s,u||0,l,a,!!a):(e.stopAnimation(),e.attr(i),a&&a())}else e.stopAnimation(),e.attr(i),a&&a()}function Io(t,e,i,n,o){Mo(!0,t,e,i,n,o)}function To(t,e,i,n,o){Mo(!1,t,e,i,n,o)}function Ao(t,e){for(var i=_t([]);t&&t!==e;)bt(i,t.getLocalTransform(),i),t=t.parent;return i}function Do(t,e,i){return e&&!c(e)&&(e=Tw.getLocalTransform(e)),i&&(e=Tt([],e)),Q([],t,e)}function Co(t,e,i){var n=0===e[4]||0===e[5]||0===e[0]?1:Math.abs(2*e[4]/e[0]),o=0===e[4]||0===e[5]||0===e[2]?1:Math.abs(2*e[4]/e[2]),a=["left"===t?-n:"right"===t?n:0,"top"===t?-o:"bottom"===t?o:0];return a=Do(a,e,i),Math.abs(a[0])>Math.abs(a[1])?a[0]>0?"right":"left":a[1]>0?"bottom":"top"}function Lo(t,e,i,n){function o(t){var e={position:F(t.position),rotation:t.rotation};return t.shape&&(e.shape=a({},t.shape)),e}if(t&&e){var r=function(t){var e={};return t.traverse(function(t){!t.isGroup&&t.anid&&(e[t.anid]=t)}),e}(t);e.traverse(function(t){if(!t.isGroup&&t.anid){var e=r[t.anid];if(e){var n=o(t);t.attr(o(e)),Io(t,n,i,t.dataIndex)}}})}}function ko(t,e){return f(t,function(t){var i=t[0];i=LM(i,e.x),i=kM(i,e.x+e.width);var n=t[1];return n=LM(n,e.y),n=kM(n,e.y+e.height),[i,n]})}function Po(t,e,i){var n=(e=a({rectHover:!0},e)).style={strokeNoScale:!0};if(i=i||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(n.image=t.slice(8),r(n,i),new fi(e)):Xn(t.replace("path://",""),e,i,"center")}function No(t,e,i){this.parentModel=e,this.ecModel=i,this.option=t}function Oo(t,e,i){for(var n=0;n0){if(t<=e[0])return i[0];if(t>=e[1])return i[1]}else{if(t>=e[0])return i[0];if(t<=e[1])return i[1]}else{if(t===e[0])return i[0];if(t===e[1])return i[1]}return(t-e[0])/o*a+i[0]}function Vo(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?zo(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function Go(t,e,i){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),i?t:+t}function Fo(t){return t.sort(function(t,e){return t-e}),t}function Wo(t){if(t=+t,isNaN(t))return 0;for(var e=1,i=0;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Ho(t){var e=t.toString(),i=e.indexOf("e");if(i>0){var n=+e.slice(i+1);return n<0?-n:0}var o=e.indexOf(".");return o<0?0:e.length-1-o}function Zo(t,e){var i=Math.log,n=Math.LN10,o=Math.floor(i(t[1]-t[0])/n),a=Math.round(i(Math.abs(e[1]-e[0]))/n),r=Math.min(Math.max(-o+a,0),20);return isFinite(r)?r:20}function Uo(t,e,i){if(!t[e])return 0;var n=p(t,function(t,e){return t+(isNaN(e)?0:e)},0);if(0===n)return 0;for(var o=Math.pow(10,i),a=f(t,function(t){return(isNaN(t)?0:t)/n*o*100}),r=100*o,s=f(a,function(t){return Math.floor(t)}),l=p(s,function(t,e){return t+e},0),u=f(a,function(t,e){return t-s[e]});lh&&(h=u[d],c=d);++s[c],u[c]=0,++l}return s[e]/o}function Xo(t){var e=2*Math.PI;return(t%e+e)%e}function jo(t){return t>-UM&&t=-20?+t.toFixed(n<0?-n:0):t}function Jo(t){function e(t,i,n){return t.interval[n]=0}function ta(t){return isNaN(t)?"-":(t=(t+"").split("."))[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(t.length>1?"."+t[1]:"")}function ea(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()}),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}function ia(t){return null==t?"":(t+"").replace(KM,function(t,e){return $M[e]})}function na(t,e,i){y(e)||(e=[e]);var n=e.length;if(!n)return"";for(var o=e[0].$vars||[],a=0;a':'':{renderMode:o,content:"{marker"+a+"|} ",style:{color:i}}:""}function ra(t,e){return t+="","0000".substr(0,e-t.length)+t}function sa(t,e,i){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var n=Yo(e),o=i?"UTC":"",a=n["get"+o+"FullYear"](),r=n["get"+o+"Month"]()+1,s=n["get"+o+"Date"](),l=n["get"+o+"Hours"](),u=n["get"+o+"Minutes"](),h=n["get"+o+"Seconds"](),c=n["get"+o+"Milliseconds"]();return t=t.replace("MM",ra(r,2)).replace("M",r).replace("yyyy",a).replace("yy",a%100).replace("dd",ra(s,2)).replace("d",s).replace("hh",ra(l,2)).replace("h",l).replace("mm",ra(u,2)).replace("m",u).replace("ss",ra(h,2)).replace("s",h).replace("SSS",ra(c,3))}function la(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}function ua(t,e,i,n,o){var a=0,r=0;null==n&&(n=1/0),null==o&&(o=1/0);var s=0;e.eachChild(function(l,u){var h,c,d=l.position,f=l.getBoundingRect(),p=e.childAt(u+1),g=p&&p.getBoundingRect();if("horizontal"===t){var m=f.width+(g?-g.x+f.x:0);(h=a+m)>n||l.newline?(a=0,h=m,r+=s+i,s=f.height):s=Math.max(s,f.height)}else{var v=f.height+(g?-g.y+f.y:0);(c=r+v)>o||l.newline?(a+=s+i,r=0,c=v,s=f.width):s=Math.max(s,f.width)}l.newline||(d[0]=a,d[1]=r,"horizontal"===t?a=h+i:r=c+i)})}function ha(t,e,i){var n=e.width,o=e.height,a=Vo(t.x,n),r=Vo(t.y,o),s=Vo(t.x2,n),l=Vo(t.y2,o);return(isNaN(a)||isNaN(parseFloat(t.x)))&&(a=0),(isNaN(s)||isNaN(parseFloat(t.x2)))&&(s=n),(isNaN(r)||isNaN(parseFloat(t.y)))&&(r=0),(isNaN(l)||isNaN(parseFloat(t.y2)))&&(l=o),i=qM(i||0),{width:Math.max(s-a-i[1]-i[3],0),height:Math.max(l-r-i[0]-i[2],0)}}function ca(t,e,i){i=qM(i||0);var n=e.width,o=e.height,a=Vo(t.left,n),r=Vo(t.top,o),s=Vo(t.right,n),l=Vo(t.bottom,o),u=Vo(t.width,n),h=Vo(t.height,o),c=i[2]+i[0],d=i[1]+i[3],f=t.aspect;switch(isNaN(u)&&(u=n-s-d-a),isNaN(h)&&(h=o-l-c-r),null!=f&&(isNaN(u)&&isNaN(h)&&(f>n/o?u=.8*n:h=.8*o),isNaN(u)&&(u=f*h),isNaN(h)&&(h=u/f)),isNaN(a)&&(a=n-s-u-d),isNaN(r)&&(r=o-l-h-c),t.left||t.right){case"center":a=n/2-u/2-i[3];break;case"right":a=n-u-d}switch(t.top||t.bottom){case"middle":case"center":r=o/2-h/2-i[0];break;case"bottom":r=o-h-c}a=a||0,r=r||0,isNaN(u)&&(u=n-d-a-(s||0)),isNaN(h)&&(h=o-c-r-(l||0));var p=new de(a+i[3],r+i[0],u,h);return p.margin=i,p}function da(t,e,i,n,o){var a=!o||!o.hv||o.hv[0],s=!o||!o.hv||o.hv[1],l=o&&o.boundingMode||"all";if(a||s){var u;if("raw"===l)u="group"===t.type?new de(0,0,+e.width||0,+e.height||0):t.getBoundingRect();else if(u=t.getBoundingRect(),t.needLocalTransform()){var h=t.getLocalTransform();(u=u.clone()).applyTransform(h)}e=ca(r({width:u.width,height:u.height},e),i,n);var c=t.position,d=a?e.x-u.x:0,f=s?e.y-u.y:0;t.attr("position","raw"===l?[d,f]:[c[0]+d,c[1]+f])}}function fa(t,e){return null!=t[oI[e][0]]||null!=t[oI[e][1]]&&null!=t[oI[e][2]]}function pa(t,e,i){function n(i,n){var r={},l=0,u={},h=0;if(iI(i,function(e){u[e]=t[e]}),iI(i,function(t){o(e,t)&&(r[t]=u[t]=e[t]),a(r,t)&&l++,a(u,t)&&h++}),s[n])return a(e,i[1])?u[i[2]]=null:a(e,i[2])&&(u[i[1]]=null),u;if(2!==h&&l){if(l>=2)return r;for(var c=0;ce)return t[n];return t[i-1]}function ya(t){var e=t.get("coordinateSystem"),i={coordSysName:e,coordSysDims:[],axisMap:R(),categoryAxisMap:R()},n=fI[e];if(n)return n(t,i,i.axisMap,i.categoryAxisMap),i}function xa(t){return"category"===t.get("type")}function _a(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===vI?{}:[]),this.sourceFormat=t.sourceFormat||yI,this.seriesLayoutBy=t.seriesLayoutBy||_I,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&R(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}function wa(t){var e=t.option.source,i=yI;if(S(e))i=xI;else if(y(e)){0===e.length&&(i=gI);for(var n=0,o=e.length;n=e:"max"===i?t<=e:t===e}function Xa(t,e){return t.join(",")===e.join(",")}function ja(t,e){AI(e=e||{},function(e,i){if(null!=e){var n=t[i];if(lI.hasClass(i)){e=Di(e);var o=Pi(n=Di(n),e);t[i]=CI(o,function(t){return t.option&&t.exist?LI(t.exist,t.option,!0):t.exist||t.option})}else t[i]=LI(n,e,!0)}})}function Ya(t){var e=t&&t.itemStyle;if(e)for(var i=0,o=OI.length;i=0;p--){var g=t[p];if(s||(d=g.data.rawIndexOf(g.stackedByDimension,c)),d>=0){var m=g.data.getByRawIndex(g.stackResultDimension,d);if(h>=0&&m>0||h<=0&&m<0){h+=m,f=m;break}}}return n[0]=h,n[1]=f,n});r.hostModel.setData(l),e.data=l})}function rr(t,e){_a.isInstance(t)||(t=_a.seriesDataToSource(t)),this._source=t;var i=this._data=t.data,n=t.sourceFormat;n===xI&&(this._offset=0,this._dimSize=e,this._data=i),a(this,GI[n===gI?n+"_"+t.seriesLayoutBy:n])}function sr(){return this._data.length}function lr(t){return this._data[t]}function ur(t){for(var e=0;ee.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Mr(t,e){d(t.CHANGABLE_METHODS,function(i){t.wrapMethod(i,v(Ir,e))})}function Ir(t){var e=Tr(t);e&&e.setOutputEnd(this.count())}function Tr(t){var e=(t.ecModel||{}).scheduler,i=e&&e.getPipeline(t.uid);if(i){var n=i.currentTask;if(n){var o=n.agentStubMap;o&&(n=o.get(t.uid))}return n}}function Ar(){this.group=new tb,this.uid=Ro("viewChart"),this.renderTask=gr({plan:Lr,reset:kr}),this.renderTask.context={view:this}}function Dr(t,e){if(t&&(t.trigger(e),"group"===t.type))for(var i=0;i=0?n():c=setTimeout(n,-a),u=o};return d.clear=function(){c&&(clearTimeout(c),c=null)},d.debounceNextCall=function(t){l=t},d}function Nr(t,e,i,n){var o=t[e];if(o){var a=o[iT]||o,r=o[oT];if(o[nT]!==i||r!==n){if(null==i||!n)return t[e]=a;(o=t[e]=Pr(a,i,"debounce"===n))[iT]=a,o[oT]=n,o[nT]=i}return o}}function Or(t,e){var i=t[e];i&&i[iT]&&(t[e]=i[iT])}function Er(t,e,i,n){this.ecInstance=t,this.api=e,this.unfinished;var i=this._dataProcessorHandlers=i.slice(),n=this._visualHandlers=n.slice();this._allHandlers=i.concat(n),this._stageTaskMap=R()}function Rr(t,e,i,n,o){function a(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}o=o||{};var r;d(e,function(e,s){if(!o.visualType||o.visualType===e.visualType){var l=t._stageTaskMap.get(e.uid),u=l.seriesTaskMap,h=l.overallTask;if(h){var c,d=h.agentStubMap;d.each(function(t){a(o,t)&&(t.dirty(),c=!0)}),c&&h.dirty(),hT(h,n);var f=t.getPerformArgs(h,o.block);d.each(function(t){t.perform(f)}),r|=h.perform(f)}else u&&u.each(function(s,l){a(o,s)&&s.dirty();var u=t.getPerformArgs(s,o.block);u.skip=!e.performRawSeries&&i.isSeriesFiltered(s.context.model),hT(s,n),r|=s.perform(u)})}}),t.unfinished|=r}function zr(t,e,i,n,o){function a(i){var a=i.uid,s=r.get(a)||r.set(a,gr({plan:Hr,reset:Zr,count:Xr}));s.context={model:i,ecModel:n,api:o,useClearVisual:e.isVisual&&!e.isLayout,plan:e.plan,reset:e.reset,scheduler:t},jr(t,i,s)}var r=i.seriesTaskMap||(i.seriesTaskMap=R()),s=e.seriesType,l=e.getTargetSeries;e.createOnAllSeries?n.eachRawSeries(a):s?n.eachRawSeriesByType(s,a):l&&l(n,o).each(a);var u=t._pipelineMap;r.each(function(t,e){u.get(e)||(t.dispose(),r.removeKey(e))})}function Br(t,e,i,n,o){function a(e){var i=e.uid,n=s.get(i);n||(n=s.set(i,gr({reset:Gr,onDirty:Wr})),r.dirty()),n.context={model:e,overallProgress:h,modifyOutputEnd:c},n.agent=r,n.__block=h,jr(t,e,n)}var r=i.overallTask=i.overallTask||gr({reset:Vr});r.context={ecModel:n,api:o,overallReset:e.overallReset,scheduler:t};var s=r.agentStubMap=r.agentStubMap||R(),l=e.seriesType,u=e.getTargetSeries,h=!0,c=e.modifyOutputEnd;l?n.eachRawSeriesByType(l,a):u?u(n,o).each(a):(h=!1,d(n.getSeries(),a));var f=t._pipelineMap;s.each(function(t,e){f.get(e)||(t.dispose(),r.dirty(),s.removeKey(e))})}function Vr(t){t.overallReset(t.ecModel,t.api,t.payload)}function Gr(t,e){return t.overallProgress&&Fr}function Fr(){this.agent.dirty(),this.getDownstream().dirty()}function Wr(){this.agent&&this.agent.dirty()}function Hr(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function Zr(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=Di(t.reset(t.model,t.ecModel,t.api,t.payload));return e.length>1?f(e,function(t,e){return Ur(e)}):cT}function Ur(t){return function(e,i){var n=i.data,o=i.resetDefines[t];if(o&&o.dataEach)for(var a=e.start;a0?parseInt(n,10)/100:n?parseFloat(n):0;var o=i.getAttribute("stop-color")||"#000000";e.addColorStop(n,o)}i=i.nextSibling}}function Qr(t,e){t&&t.__inheritedStyle&&(e.__inheritedStyle||(e.__inheritedStyle={}),r(e.__inheritedStyle,t.__inheritedStyle))}function ts(t){for(var e=P(t).split(_T),i=[],n=0;n0;a-=2){var r=o[a],s=o[a-1];switch(n=n||xt(),s){case"translate":r=P(r).split(_T),St(n,n,[parseFloat(r[0]),parseFloat(r[1]||0)]);break;case"scale":r=P(r).split(_T),It(n,n,[parseFloat(r[0]),parseFloat(r[1]||r[0])]);break;case"rotate":r=P(r).split(_T),Mt(n,n,parseFloat(r[0]));break;case"skew":r=P(r).split(_T),console.warn("Skew transform is not supported yet");break;case"matrix":r=P(r).split(_T);n[0]=parseFloat(r[0]),n[1]=parseFloat(r[1]),n[2]=parseFloat(r[2]),n[3]=parseFloat(r[3]),n[4]=parseFloat(r[4]),n[5]=parseFloat(r[5])}}e.setLocalTransform(n)}}function os(t){var e=t.getAttribute("style"),i={};if(!e)return i;var n={};TT.lastIndex=0;for(var o;null!=(o=TT.exec(e));)n[o[1]]=o[2];for(var a in ST)ST.hasOwnProperty(a)&&null!=n[a]&&(i[ST[a]]=n[a]);return i}function as(t,e,i){var n=e/t.width,o=i/t.height,a=Math.min(n,o);return{scale:[a,a],position:[-(t.x+t.width/2)*a+e/2,-(t.y+t.height/2)*a+i/2]}}function rs(t,e){return(new $r).parse(t,e)}function ss(t){return function(e,i,n){e=e&&e.toLowerCase(),fw.prototype[t].call(this,e,i,n)}}function ls(){fw.call(this)}function us(t,e,n){function o(t,e){return t.__prio-e.__prio}n=n||{},"string"==typeof e&&(e=JT[e]),this.id,this.group,this._dom=t;var a=this._zr=Ii(t,{renderer:n.renderer||"canvas",devicePixelRatio:n.devicePixelRatio,width:n.width,height:n.height});this._throttledZrFlush=Pr(m(a.flush,a),17),(e=i(e))&&BI(e,!0),this._theme=e,this._chartsViews=[],this._chartsMap={},this._componentsViews=[],this._componentsMap={},this._coordSysMgr=new Fa;var r=this._api=As(this);_e($T,o),_e(YT,o),this._scheduler=new Er(this,r,YT,$T),fw.call(this,this._ecEventProcessor=new Ds),this._messageCenter=new ls,this._initEvents(),this.resize=m(this.resize,this),this._pendingActions=[],a.animation.on("frame",this._onframe,this),vs(a,this),N(this)}function hs(t,e,i){var n,o=this._model,a=this._coordSysMgr.getCoordinateSystems();e=Vi(o,e);for(var r=0;re.get("hoverLayerThreshold")&&!U_.node&&i.traverse(function(t){t.isGroup||(t.useHoverLayer=!0)})}function Is(t,e){var i=t.get("blendMode")||null;e.group.traverse(function(t){t.isGroup||t.style.blend!==i&&t.setStyle("blend",i),t.eachPendingDisplayable&&t.eachPendingDisplayable(function(t){t.setStyle("blend",i)})})}function Ts(t,e){var i=t.get("z"),n=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=n&&(t.zlevel=n))})}function As(t){var e=t._coordSysMgr;return a(new Ga(t),{getCoordinateSystems:m(e.getCoordinateSystems,e),getComponentByElement:function(e){for(;e;){var i=e.__ecComponentInfo;if(null!=i)return t._model.getComponent(i.mainType,i.index);e=e.parent}}})}function Ds(){this.eventInfo}function Cs(t){function e(t,e){for(var n=0;n65535?dA:pA}function Js(t){var e=t.constructor;return e===Array?t.slice():new e(t)}function Qs(t,e){d(gA.concat(e.__wrappedMethods||[]),function(i){e.hasOwnProperty(i)&&(t[i]=e[i])}),t.__wrappedMethods=e.__wrappedMethods,d(mA,function(n){t[n]=i(e[n])}),t._calculationInfo=a(e._calculationInfo)}function tl(t,e,i,n,o){var a=cA[e.type],r=n-1,s=e.name,l=t[s][r];if(l&&l.length=0?this._indices[t]:-1}function al(t,e){var i=t._idList[e];return null==i&&(i=il(t,t._idDimIdx,e)),null==i&&(i=hA+e),i}function rl(t){return y(t)||(t=[t]),t}function sl(t,e){var i=t.dimensions,n=new vA(f(i,t.getDimensionInfo,t),t.hostModel);Qs(n,t);for(var o=n._storage={},a=t._storage,r=0;r=0?(o[s]=ll(a[s]),n._rawExtent[s]=ul(),n._extent[s]=null):o[s]=a[s])}return n}function ll(t){for(var e=new Array(t.length),i=0;in&&(r=o.interval=n);var s=o.intervalPrecision=Ml(r);return Tl(o.niceTickExtent=[MA(Math.ceil(t[0]/r)*r,s),MA(Math.floor(t[1]/r)*r,s)],t),o}function Ml(t){return Ho(t)+2}function Il(t,e,i){t[e]=Math.max(Math.min(t[e],i[1]),i[0])}function Tl(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),Il(t,0,e),Il(t,1,e),t[0]>t[1]&&(t[0]=t[1])}function Al(t,e,i,n){var o=[];if(!t)return o;e[0]1e4)return[];return e[1]>(o.length?o[o.length-1]:i[1])&&o.push(e[1]),o}function Dl(t){return t.get("stack")||AA+t.seriesIndex}function Cl(t){return t.dim+t.index}function Ll(t){var e=[],i=t.axis;if("category"===i.type){for(var n=i.getBandWidth(),o=0;o=0?"p":"n",b=m;p&&(o[r][_]||(o[r][_]={p:m,n:m}),b=o[r][_][w]);var S,M,I,T;if(g)S=b,M=(A=i.dataToPoint([x,_]))[1]+l,I=A[0]-m,T=u,Math.abs(I)a[1]?(n=a[1],o=a[0]):(n=a[0],o=a[1]);var r=e.toGlobalCoord(e.dataToCoord(0));return ro&&(r=o),r}function Vl(t,e){return VA(t,BA(e))}function Gl(t,e){var i,n,o,a=t.type,r=e.getMin(),s=e.getMax(),l=null!=r,u=null!=s,h=t.getExtent();"ordinal"===a?i=e.getCategories().length:(y(n=e.get("boundaryGap"))||(n=[n||0,n||0]),"boolean"==typeof n[0]&&(n=[0,0]),n[0]=Vo(n[0],1),n[1]=Vo(n[1],1),o=h[1]-h[0]||Math.abs(h[0])),null==r&&(r="ordinal"===a?i?0:NaN:h[0]-n[0]*o),null==s&&(s="ordinal"===a?i?i-1:NaN:h[1]+n[1]*o),"dataMin"===r?r=h[0]:"function"==typeof r&&(r=r({min:h[0],max:h[1]})),"dataMax"===s?s=h[1]:"function"==typeof s&&(s=s({min:h[0],max:h[1]})),(null==r||!isFinite(r))&&(r=NaN),(null==s||!isFinite(s))&&(s=NaN),t.setBlank(I(r)||I(s)||"ordinal"===a&&!t.getOrdinalMeta().categories.length),e.getNeedCrossZero()&&(r>0&&s>0&&!l&&(r=0),r<0&&s<0&&!u&&(s=0));var c=e.ecModel;if(c&&"time"===a){var f,p=kl("bar",c);if(d(p,function(t){f|=t.getBaseAxis()===e.axis}),f){var g=Pl(p),m=Fl(r,s,e,g);r=m.min,s=m.max}}return[r,s]}function Fl(t,e,i,n){var o=i.axis.getExtent(),a=o[1]-o[0],r=Ol(n,i.axis);if(void 0===r)return{min:t,max:e};var s=1/0;d(r,function(t){s=Math.min(t.offset,s)});var l=-1/0;d(r,function(t){l=Math.max(t.offset+t.width,l)}),s=Math.abs(s),l=Math.abs(l);var u=s+l,h=e-t,c=h/(1-(s+l)/a)-h;return e+=c*(l/u),t-=c*(s/u),{min:t,max:e}}function Wl(t,e){var i=Gl(t,e),n=null!=e.getMin(),o=null!=e.getMax(),a=e.get("splitNumber");"log"===t.type&&(t.base=e.get("logBase"));var r=t.type;t.setExtent(i[0],i[1]),t.niceExtent({splitNumber:a,fixMin:n,fixMax:o,minInterval:"interval"===r||"time"===r?e.get("minInterval"):null,maxInterval:"interval"===r||"time"===r?e.get("maxInterval"):null});var s=e.get("interval");null!=s&&t.setInterval&&t.setInterval(s)}function Hl(t,e){if(e=e||t.get("type"))switch(e){case"category":return new SA(t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),[1/0,-1/0]);case"value":return new TA;default:return(xl.getClass(e)||TA).create(t)}}function Zl(t){var e=t.scale.getExtent(),i=e[0],n=e[1];return!(i>0&&n>0||i<0&&n<0)}function Ul(t){var e=t.getLabelModel().get("formatter"),i="category"===t.type?t.scale.getExtent()[0]:null;return"string"==typeof e?e=function(e){return function(i){return i=t.scale.getLabel(i),e.replace("{value}",null!=i?i:"")}}(e):"function"==typeof e?function(n,o){return null!=i&&(o=n-i),e(Xl(t,n),o)}:function(e){return t.scale.getLabel(e)}}function Xl(t,e){return"category"===t.type?t.scale.getLabel(e):e}function jl(t){var e=t.model,i=t.scale;if(e.get("axisLabel.show")&&!i.isBlank()){var n,o,a="category"===t.type,r=i.getExtent();o=a?i.count():(n=i.getTicks()).length;var s,l=t.getLabelModel(),u=Ul(t),h=1;o>40&&(h=Math.ceil(o/40));for(var c=0;c>1^-(1&s),l=l>>1^-(1&l),o=s+=o,a=l+=a,n.push([s/i,l/i])}return n}function ou(t){return"category"===t.type?ru(t):uu(t)}function au(t,e){return"category"===t.type?lu(t,e):{ticks:t.scale.getTicks()}}function ru(t){var e=t.getLabelModel(),i=su(t,e);return!e.get("show")||t.scale.isBlank()?{labels:[],labelCategoryInterval:i.labelCategoryInterval}:i}function su(t,e){var i=hu(t,"labels"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;return a=x(n)?vu(t,n):mu(t,r="auto"===n?fu(t):n),du(i,n,{labels:a,labelCategoryInterval:r})}function lu(t,e){var i=hu(t,"ticks"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;if(e.get("show")&&!t.scale.isBlank()||(a=[]),x(n))a=vu(t,n,!0);else if("auto"===n){var s=su(t,t.getLabelModel());r=s.labelCategoryInterval,a=f(s.labels,function(t){return t.tickValue})}else a=mu(t,r=n,!0);return du(i,n,{ticks:a,tickCategoryInterval:r})}function uu(t){var e=t.scale.getTicks(),i=Ul(t);return{labels:f(e,function(e,n){return{formattedLabel:i(e,n),rawLabel:t.scale.getLabel(e),tickValue:e}})}}function hu(t,e){return nD(t)[e]||(nD(t)[e]=[])}function cu(t,e){for(var i=0;i40&&(s=Math.max(1,Math.floor(r/40)));for(var l=a[0],u=t.dataToCoord(l+1)-t.dataToCoord(l),h=Math.abs(u*Math.cos(n)),c=Math.abs(u*Math.sin(n)),d=0,f=0;l<=a[1];l+=s){var p=0,g=0,m=ke(i(l),e.font,"center","top");p=1.3*m.width,g=1.3*m.height,d=Math.max(d,p,7),f=Math.max(f,g,7)}var v=d/h,y=f/c;isNaN(v)&&(v=1/0),isNaN(y)&&(y=1/0);var x=Math.max(0,Math.floor(Math.min(v,y))),_=nD(t.model),w=_.lastAutoInterval,b=_.lastTickCount;return null!=w&&null!=b&&Math.abs(w-x)<=1&&Math.abs(b-r)<=1&&w>x?x=w:(_.lastTickCount=r,_.lastAutoInterval=x),x}function gu(t){var e=t.getLabelModel();return{axisRotate:t.getRotate?t.getRotate():t.isHorizontal&&!t.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}function mu(t,e,i){function n(t){l.push(i?t:{formattedLabel:o(t),rawLabel:a.getLabel(t),tickValue:t})}var o=Ul(t),a=t.scale,r=a.getExtent(),s=t.getLabelModel(),l=[],u=Math.max((e||0)+1,1),h=r[0],c=a.count();0!==h&&u>1&&c/u>2&&(h=Math.round(Math.ceil(h/u)*u));var d=Kl(t),f=s.get("showMinLabel")||d,p=s.get("showMaxLabel")||d;f&&h!==r[0]&&n(r[0]);for(var g=h;g<=r[1];g+=u)n(g);return p&&g!==r[1]&&n(r[1]),l}function vu(t,e,i){var n=t.scale,o=Ul(t),a=[];return d(n.getTicks(),function(t){var r=n.getLabel(t);e(t,r)&&a.push(i?t:{formattedLabel:o(t),rawLabel:r,tickValue:t})}),a}function yu(t,e){var i=(t[1]-t[0])/e/2;t[0]+=i,t[1]-=i}function xu(t,e,i,n,o){function a(t,e){return h?t>e:t0&&(t.coord-=u/(2*(e+1)))}),s={coord:e[r-1].coord+u},e.push(s)}var h=l[0]>l[1];a(e[0].coord,l[0])&&(o?e[0].coord=l[0]:e.shift()),o&&a(l[0],e[0].coord)&&e.unshift({coord:l[0]}),a(l[1],s.coord)&&(o?s.coord=l[1]:e.pop()),o&&a(s.coord,l[1])&&e.push({coord:l[1]})}}function _u(t,e){var i=t.mapDimension("defaultedLabel",!0),n=i.length;if(1===n)return fr(t,e,i[0]);if(n){for(var o=[],a=0;a0?i=n[0]:n[1]<0&&(i=n[1]),i}function Ou(t,e,i,n){var o=NaN;t.stacked&&(o=i.get(i.getCalculationInfo("stackedOverDimension"),n)),isNaN(o)&&(o=t.valueStart);var a=t.baseDataOffset,r=[];return r[a]=i.get(t.baseDim,n),r[1-a]=o,e.dataToPoint(r)}function Eu(t,e){var i=[];return e.diff(t).add(function(t){i.push({cmd:"+",idx:t})}).update(function(t,e){i.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){i.push({cmd:"-",idx:t})}).execute(),i}function Ru(t){return isNaN(t[0])||isNaN(t[1])}function zu(t,e,i,n,o,a,r,s,l,u,h){return"none"!==u&&u?Bu.apply(this,arguments):Vu.apply(this,arguments)}function Bu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]);else if(l>0){var g=e[c],m="y"===u?1:0,v=(p[m]-g[m])*l;_D(bD,g),bD[m]=g[m]+v,_D(SD,p),SD[m]=p[m]-v,t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1])}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Vu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]),_D(bD,p);else if(l>0){var g=d+a,m=e[g];if(h)for(;m&&Ru(e[g]);)m=e[g+=a];var v=.5,y=e[c];if(!(m=e[g])||Ru(m))_D(SD,p);else{Ru(m)&&!h&&(m=p),U(wD,m,y);var x,_;if("x"===u||"y"===u){var w="x"===u?0:1;x=Math.abs(p[w]-y[w]),_=Math.abs(p[w]-m[w])}else x=uw(p,y),_=uw(p,m);xD(SD,p,wD,-l*(1-(v=_/(_+x))))}vD(bD,bD,s),yD(bD,bD,r),vD(SD,SD,s),yD(SD,SD,r),t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1]),xD(bD,p,wD,l*v)}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Gu(t,e){var i=[1/0,1/0],n=[-1/0,-1/0];if(e)for(var o=0;on[0]&&(n[0]=a[0]),a[1]>n[1]&&(n[1]=a[1])}return{min:e?i:n,max:e?n:i}}function Fu(t,e){if(t.length===e.length){for(var i=0;ie[0]?1:-1;e[0]+=n*i,e[1]-=n*i}return e}function Zu(t,e,i){if(!i.valueDim)return[];for(var n=[],o=0,a=e.count();oa[1]&&a.reverse();var r=o.getExtent(),s=Math.PI/180;i&&(a[0]-=.5,a[1]+=.5);var l=new hM({shape:{cx:Go(t.cx,1),cy:Go(t.cy,1),r0:Go(a[0],1),r:Go(a[1],1),startAngle:-r[0]*s,endAngle:-r[1]*s,clockwise:o.inverse}});return e&&(l.shape.endAngle=-r[0]*s,To(l,{shape:{endAngle:-r[1]*s}},n)),l}function ju(t,e,i,n){return"polar"===t.type?Xu(t,e,i,n):Uu(t,e,i,n)}function Yu(t,e,i){for(var n=e.getBaseAxis(),o="x"===n.dim||"radius"===n.dim?0:1,a=[],r=0;r=0;a--){var r=i[a].dimension,s=t.dimensions[r],l=t.getDimensionInfo(s);if("x"===(n=l&&l.coordDim)||"y"===n){o=i[a];break}}if(o){var u=e.getAxis(n),h=f(o.stops,function(t){return{coord:u.toGlobalCoord(u.dataToCoord(t.value)),color:t.color}}),c=h.length,p=o.outerColors.slice();c&&h[0].coord>h[c-1].coord&&(h.reverse(),p.reverse());var g=h[0].coord-10,m=h[c-1].coord+10,v=m-g;if(v<.001)return"transparent";d(h,function(t){t.offset=(t.coord-g)/v}),h.push({offset:c?h[c-1].offset:.5,color:p[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:p[0]||"transparent"});var y=new TM(0,0,0,0,h,!0);return y[n]=g,y[n+"2"]=m,y}}}function Ku(t,e,i){var n=t.get("showAllSymbol"),o="auto"===n;if(!n||o){var a=i.getAxesByScale("ordinal")[0];if(a&&(!o||!$u(a,e))){var r=e.mapDimension(a.dim),s={};return d(a.getViewLabels(),function(t){s[t.tickValue]=1}),function(t){return!s.hasOwnProperty(e.get(r,t))}}}}function $u(t,e){var i=t.getExtent(),n=Math.abs(i[1]-i[0])/t.scale.count();isNaN(n)&&(n=0);for(var o=e.count(),a=Math.max(1,Math.round(o/5)),r=0;rn)return!1;return!0}function Ju(t){return this._axes[t]}function Qu(t){LD.call(this,t)}function th(t,e){return e.type||(e.data?"category":"value")}function eh(t,e,i){return t.getCoordSysModel()===e}function ih(t,e,i){this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this._initCartesian(t,e,i),this.model=t}function nh(t,e,i,n){function o(t){return t.dim+"_"+t.index}i.getAxesOnZeroOf=function(){return a?[a]:[]};var a,r=t[e],s=i.model,l=s.get("axisLine.onZero"),u=s.get("axisLine.onZeroAxisIndex");if(l){if(null!=u)oh(r[u])&&(a=r[u]);else for(var h in r)if(r.hasOwnProperty(h)&&oh(r[h])&&!n[o(r[h])]){a=r[h];break}a&&(n[o(a)]=!0)}}function oh(t){return t&&"category"!==t.type&&"time"!==t.type&&Zl(t)}function ah(t,e){var i=t.getExtent(),n=i[0]+i[1];t.toGlobalCoord="x"===t.dim?function(t){return t+e}:function(t){return n-t+e},t.toLocalCoord="x"===t.dim?function(t){return t-e}:function(t){return n-t+e}}function rh(t,e){return f(VD,function(e){return t.getReferringComponents(e)[0]})}function sh(t){return"cartesian2d"===t.get("coordinateSystem")}function lh(t){var e={componentType:t.mainType,componentIndex:t.componentIndex};return e[t.mainType+"Index"]=t.componentIndex,e}function uh(t,e,i,n){var o,a,r=Xo(i-t.rotation),s=n[0]>n[1],l="start"===e&&!s||"start"!==e&&s;return jo(r-GD/2)?(a=l?"bottom":"top",o="center"):jo(r-1.5*GD)?(a=l?"top":"bottom",o="center"):(a="middle",o=r<1.5*GD&&r>GD/2?l?"left":"right":l?"right":"left"),{rotation:r,textAlign:o,textVerticalAlign:a}}function hh(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)}function ch(t,e,i){if(!Kl(t.axis)){var n=t.get("axisLabel.showMinLabel"),o=t.get("axisLabel.showMaxLabel");e=e||[],i=i||[];var a=e[0],r=e[1],s=e[e.length-1],l=e[e.length-2],u=i[0],h=i[1],c=i[i.length-1],d=i[i.length-2];!1===n?(dh(a),dh(u)):fh(a,r)&&(n?(dh(r),dh(h)):(dh(a),dh(u))),!1===o?(dh(s),dh(c)):fh(l,s)&&(o?(dh(l),dh(d)):(dh(s),dh(c)))}}function dh(t){t&&(t.ignore=!0)}function fh(t,e,i){var n=t&&t.getBoundingRect().clone(),o=e&&e.getBoundingRect().clone();if(n&&o){var a=_t([]);return Mt(a,a,-t.rotation),n.applyTransform(bt([],a,t.getLocalTransform())),o.applyTransform(bt([],a,e.getLocalTransform())),n.intersect(o)}}function ph(t){return"middle"===t||"center"===t}function gh(t,e,i){var n=e.axis;if(e.get("axisTick.show")&&!n.scale.isBlank()){for(var o=e.getModel("axisTick"),a=o.getModel("lineStyle"),s=o.get("length"),l=n.getTicksCoords(),u=[],h=[],c=t._transform,d=[],f=0;f=0||t===e}function Sh(t){var e=Mh(t);if(e){var i=e.axisPointerModel,n=e.axis.scale,o=i.option,a=i.get("status"),r=i.get("value");null!=r&&(r=n.parse(r));var s=Th(i);null==a&&(o.status=s?"show":"hide");var l=n.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==r||r>l[1])&&(r=l[1]),r0?"bottom":"top":o.width>0?"left":"right";l||kh(t.style,d,n,u,a,i,p),fo(t,d)}function Rh(t,e){var i=t.get(tC)||0;return Math.min(i,Math.abs(e.width),Math.abs(e.height))}function zh(t,e,i){var n=t.getData(),o=[],a=n.getLayout("valueAxisHorizontal")?1:0;o[1-a]=n.getLayout("valueAxisStart");var r=new nC({shape:{points:n.getLayout("largePoints")},incremental:!!i,__startPoint:o,__valueIdx:a});e.add(r),Bh(r,t,n)}function Bh(t,e,i){var n=i.getVisual("borderColor")||i.getVisual("color"),o=e.getModel("itemStyle").getItemStyle(["color","borderColor"]);t.useStyle(o),t.style.fill=null,t.style.stroke=n,t.style.lineWidth=i.getLayout("barWidth")}function Vh(t,e,i,n){var o=e.getData(),a=this.dataIndex,r=o.getName(a),s=e.get("selectedOffset");n.dispatchAction({type:"pieToggleSelect",from:t,name:r,seriesId:e.id}),o.each(function(t){Gh(o.getItemGraphicEl(t),o.getItemLayout(t),e.isSelected(o.getName(t)),s,i)})}function Gh(t,e,i,n,o){var a=(e.startAngle+e.endAngle)/2,r=Math.cos(a),s=Math.sin(a),l=i?n:0,u=[r*l,s*l];o?t.animate().when(200,{position:u}).start("bounceOut"):t.attr("position",u)}function Fh(t,e){function i(){a.ignore=a.hoverIgnore,r.ignore=r.hoverIgnore}function n(){a.ignore=a.normalIgnore,r.ignore=r.normalIgnore}tb.call(this);var o=new hM({z2:2}),a=new gM,r=new rM;this.add(o),this.add(a),this.add(r),this.updateData(t,e,!0),this.on("emphasis",i).on("normal",n).on("mouseover",i).on("mouseout",n)}function Wh(t,e,i,n,o,a,r){function s(e,i){for(var n=e;n>=0&&(t[n].y-=i,!(n>0&&t[n].y>t[n-1].y+t[n-1].height));n--);}function l(t,e,i,n,o,a){for(var r=e?Number.MAX_VALUE:0,s=0,l=t.length;s=r&&(d=r-10),!e&&d<=r&&(d=r+10),t[s].x=i+d*a,r=d}}t.sort(function(t,e){return t.y-e.y});for(var u,h=0,c=t.length,d=[],f=[],p=0;pe&&a+1t[a].y+t[a].height)return void s(a,n/2);s(i-1,n/2)}(p,c,-u),h=t[p].y+t[p].height;r-h<0&&s(c-1,h-r);for(p=0;p=i?f.push(t[p]):d.push(t[p]);l(d,!1,e,i,n,o),l(f,!0,e,i,n,o)}function Hh(t,e,i,n,o,a){for(var r=[],s=[],l=0;l3?1.4:o>1?1.2:1.1;hc(this,"zoom","zoomOnMouseWheel",t,{scale:n>0?s:1/s,originX:a,originY:r})}if(i){var l=Math.abs(n);hc(this,"scrollMove","moveOnMouseWheel",t,{scrollDelta:(n>0?1:-1)*(l>3?.4:l>1?.15:.05),originX:a,originY:r})}}}function uc(t){ic(this._zr,"globalPan")||hc(this,"zoom",null,t,{scale:t.pinchScale>1?1.1:1/1.1,originX:t.pinchX,originY:t.pinchY})}function hc(t,e,i,n,o){t.pointerChecker&&t.pointerChecker(n,o.originX,o.originY)&&(mw(n.event),cc(t,e,i,n,o))}function cc(t,e,i,n,o){o.isAvailableBehavior=m(dc,null,i,n),t.trigger(e,o)}function dc(t,e,i){var n=i[t];return!t||n&&(!_(n)||e.event[n+"Key"])}function fc(t,e,i){var n=t.target,o=n.position;o[0]+=e,o[1]+=i,n.dirty()}function pc(t,e,i,n){var o=t.target,a=t.zoomLimit,r=o.position,s=o.scale,l=t.zoom=t.zoom||1;if(l*=e,a){var u=a.min||0,h=a.max||1/0;l=Math.max(Math.min(h,l),u)}var c=l/t.zoom;t.zoom=l,r[0]-=(i-r[0])*(c-1),r[1]-=(n-r[1])*(c-1),s[0]*=c,s[1]*=c,o.dirty()}function gc(t,e,i){var n=e.getComponentByElement(t.topTarget),o=n&&n.coordinateSystem;return n&&n!==i&&!RC[n.mainType]&&o&&o.model!==i}function mc(t,e){var i=t.getItemStyle(),n=t.get("areaColor");return null!=n&&(i.fill=n),i}function vc(t,e,i,n,o){i.off("click"),i.off("mousedown"),e.get("selectedMode")&&(i.on("mousedown",function(){t._mouseDownFlag=!0}),i.on("click",function(a){if(t._mouseDownFlag){t._mouseDownFlag=!1;for(var r=a.target;!r.__regions;)r=r.parent;if(r){var s={type:("geo"===e.mainType?"geo":"map")+"ToggleSelect",batch:f(r.__regions,function(t){return{name:t.name,from:o.uid}})};s[e.mainType+"Id"]=e.id,n.dispatchAction(s),yc(e,i)}}}))}function yc(t,e){e.eachChild(function(e){d(e.__regions,function(i){e.trigger(t.isSelected(i.name)?"emphasis":"normal")})})}function xc(t,e){var i=new tb;this.uid=Ro("ec_map_draw"),this._controller=new oc(t.getZr()),this._controllerHost={target:e?i:null},this.group=i,this._updateGroup=e,this._mouseDownFlag,this._mapName,this._initialized,i.add(this._regionsGroup=new tb),i.add(this._backgroundGroup=new tb)}function _c(t){var e=this[zC];e&&e.recordVersion===this[BC]&&wc(e,t)}function wc(t,e){var i=t.circle,n=t.labelModel,o=t.hoverLabelModel,a=t.emphasisText,r=t.normalText;e?(i.style.extendFrom(mo({},o,{text:o.get("show")?a:null},{isRectText:!0,useInsideStyle:!1},!0)),i.__mapOriginalZ2=i.z2,i.z2+=NM):(mo(i.style,n,{text:n.get("show")?r:null,textPosition:n.getShallow("position")||"bottom"},{isRectText:!0,useInsideStyle:!1}),i.dirty(!1),null!=i.__mapOriginalZ2&&(i.z2=i.__mapOriginalZ2,i.__mapOriginalZ2=null))}function bc(t,e,i){var n=t.getZoom(),o=t.getCenter(),a=e.zoom,r=t.dataToPoint(o);if(null!=e.dx&&null!=e.dy){r[0]-=e.dx,r[1]-=e.dy;o=t.pointToData(r);t.setCenter(o)}if(null!=a){if(i){var s=i.min||0,l=i.max||1/0;a=Math.max(Math.min(n*a,l),s)/n}t.scale[0]*=a,t.scale[1]*=a;var u=t.position,h=(e.originX-u[0])*(a-1),c=(e.originY-u[1])*(a-1);u[0]-=h,u[1]-=c,t.updateTransform();o=t.pointToData(r);t.setCenter(o),t.setZoom(a*n)}return{center:t.getCenter(),zoom:t.getZoom()}}function Sc(){Tw.call(this)}function Mc(t){this.name=t,this.zoomLimit,Tw.call(this),this._roamTransformable=new Sc,this._rawTransformable=new Sc,this._center,this._zoom}function Ic(t,e,i,n){var o=i.seriesModel,a=o?o.coordinateSystem:null;return a===this?a[t](n):null}function Tc(t,e,i,n){Mc.call(this,t),this.map=e;var o=OC.load(e,i);this._nameCoordMap=o.nameCoordMap,this._regionsMap=o.regionsMap,this._invertLongitute=null==n||n,this.regions=o.regions,this._rect=o.boundingRect}function Ac(t,e,i,n){var o=i.geoModel,a=i.seriesModel,r=o?o.coordinateSystem:a?a.coordinateSystem||(a.getReferringComponents("geo")[0]||{}).coordinateSystem:null;return r===this?r[t](n):null}function Dc(t,e){var i=t.get("boundingCoords");if(null!=i){var n=i[0],o=i[1];isNaN(n[0])||isNaN(n[1])||isNaN(o[0])||isNaN(o[1])||this.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1])}var a,r=this.getBoundingRect(),s=t.get("layoutCenter"),l=t.get("layoutSize"),u=e.getWidth(),h=e.getHeight(),c=r.width/r.height*this.aspectScale,d=!1;s&&l&&(s=[Vo(s[0],u),Vo(s[1],h)],l=Vo(l,Math.min(u,h)),isNaN(s[0])||isNaN(s[1])||isNaN(l)||(d=!0));if(d){var f={};c>1?(f.width=l,f.height=l/c):(f.height=l,f.width=l*c),f.y=s[1]-f.height/2,f.x=s[0]-f.width/2}else(a=t.getBoxLayoutParams()).aspect=c,f=ca(a,{width:u,height:h});this.setViewRect(f.x,f.y,f.width,f.height),this.setCenter(t.get("center")),this.setZoom(t.get("zoom"))}function Cc(t,e){d(e.get("geoCoord"),function(e,i){t.addGeoCoord(i,e)})}function Lc(t,e){var i={};return d(t,function(t){t.each(t.mapDimension("value"),function(e,n){var o="ec-"+t.getName(n);i[o]=i[o]||[],isNaN(e)||i[o].push(e)})}),t[0].map(t[0].mapDimension("value"),function(n,o){for(var a="ec-"+t[0].getName(o),r=0,s=1/0,l=-1/0,u=i[a].length,h=0;h=0;o--){var a=i[o];a.hierNode={defaultAncestor:null,ancestor:a,prelim:0,modifier:0,change:0,shift:0,i:o,thread:null},n.push(a)}}function Wc(t,e){var i=t.isExpand?t.children:[],n=t.parentNode.children,o=t.hierNode.i?n[t.hierNode.i-1]:null;if(i.length){jc(t);var a=(i[0].hierNode.prelim+i[i.length-1].hierNode.prelim)/2;o?(t.hierNode.prelim=o.hierNode.prelim+e(t,o),t.hierNode.modifier=t.hierNode.prelim-a):t.hierNode.prelim=a}else o&&(t.hierNode.prelim=o.hierNode.prelim+e(t,o));t.parentNode.hierNode.defaultAncestor=Yc(t,o,t.parentNode.hierNode.defaultAncestor||n[0],e)}function Hc(t){var e=t.hierNode.prelim+t.parentNode.hierNode.modifier;t.setLayout({x:e},!0),t.hierNode.modifier+=t.parentNode.hierNode.modifier}function Zc(t){return arguments.length?t:Qc}function Uc(t,e){var i={};return t-=Math.PI/2,i.x=e*Math.cos(t),i.y=e*Math.sin(t),i}function Xc(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}function jc(t){for(var e=t.children,i=e.length,n=0,o=0;--i>=0;){var a=e[i];a.hierNode.prelim+=n,a.hierNode.modifier+=n,o+=a.hierNode.change,n+=a.hierNode.shift+o}}function Yc(t,e,i,n){if(e){for(var o=t,a=t,r=a.parentNode.children[0],s=e,l=o.hierNode.modifier,u=a.hierNode.modifier,h=r.hierNode.modifier,c=s.hierNode.modifier;s=qc(s),a=Kc(a),s&&a;){o=qc(o),r=Kc(r),o.hierNode.ancestor=t;var d=s.hierNode.prelim+c-a.hierNode.prelim-u+n(s,a);d>0&&(Jc($c(s,t,i),t,d),u+=d,l+=d),c+=s.hierNode.modifier,u+=a.hierNode.modifier,l+=o.hierNode.modifier,h+=r.hierNode.modifier}s&&!qc(o)&&(o.hierNode.thread=s,o.hierNode.modifier+=c-l),a&&!Kc(r)&&(r.hierNode.thread=a,r.hierNode.modifier+=u-h,i=t)}return i}function qc(t){var e=t.children;return e.length&&t.isExpand?e[e.length-1]:t.hierNode.thread}function Kc(t){var e=t.children;return e.length&&t.isExpand?e[0]:t.hierNode.thread}function $c(t,e,i){return t.hierNode.ancestor.parentNode===e.parentNode?t.hierNode.ancestor:i}function Jc(t,e,i){var n=i/(e.hierNode.i-t.hierNode.i);e.hierNode.change-=n,e.hierNode.shift+=i,e.hierNode.modifier+=i,e.hierNode.prelim+=i,t.hierNode.change+=n}function Qc(t,e){return t.parentNode===e.parentNode?1:2}function td(t,e){var i=t.getItemLayout(e);return i&&!isNaN(i.x)&&!isNaN(i.y)&&"none"!==t.getItemVisual(e,"symbol")}function ed(t,e,i){return i.itemModel=e,i.itemStyle=e.getModel("itemStyle").getItemStyle(),i.hoverItemStyle=e.getModel("emphasis.itemStyle").getItemStyle(),i.lineStyle=e.getModel("lineStyle").getLineStyle(),i.labelModel=e.getModel("label"),i.hoverLabelModel=e.getModel("emphasis.label"),!1===t.isExpand&&0!==t.children.length?i.symbolInnerColor=i.itemStyle.fill:i.symbolInnerColor="#fff",i}function id(t,e,i,n,o,a){var s=!i,l=t.tree.getNodeByDataIndex(e),a=ed(l,l.getModel(),a),u=t.tree.root,h=l.parentNode===u?l:l.parentNode||l,c=t.getItemGraphicEl(h.dataIndex),d=h.getLayout(),f=c?{x:c.position[0],y:c.position[1],rawX:c.__radialOldRawX,rawY:c.__radialOldRawY}:d,p=l.getLayout();s?(i=new wu(t,e,a)).attr("position",[f.x,f.y]):i.updateData(t,e,a),i.__radialOldRawX=i.__radialRawX,i.__radialOldRawY=i.__radialRawY,i.__radialRawX=p.rawX,i.__radialRawY=p.rawY,n.add(i),t.setItemGraphicEl(e,i),Io(i,{position:[p.x,p.y]},o);var g=i.getSymbolPath();if("radial"===a.layout){var m,v,y=u.children[0],x=y.getLayout(),_=y.children.length;if(p.x===x.x&&!0===l.isExpand){var w={};w.x=(y.children[0].getLayout().x+y.children[_-1].getLayout().x)/2,w.y=(y.children[0].getLayout().y+y.children[_-1].getLayout().y)/2,(m=Math.atan2(w.y-x.y,w.x-x.x))<0&&(m=2*Math.PI+m),(v=w.xx.x)||(m-=Math.PI);var b=v?"left":"right";g.setStyle({textPosition:b,textRotation:-m,textOrigin:"center",verticalAlign:"middle"})}if(l.parentNode&&l.parentNode!==u){var S=i.__edge;S||(S=i.__edge=new bM({shape:od(a,f,f),style:r({opacity:0,strokeNoScale:!0},a.lineStyle)})),Io(S,{shape:od(a,d,p),style:{opacity:1}},o),n.add(S)}}function nd(t,e,i,n,o,a){for(var r,s=t.tree.getNodeByDataIndex(e),l=t.tree.root,a=ed(s,s.getModel(),a),u=s.parentNode===l?s:s.parentNode||s;null==(r=u.getLayout());)u=u.parentNode===l?u:u.parentNode||u;Io(i,{position:[r.x+1,r.y+1]},o,function(){n.remove(i),t.setItemGraphicEl(e,null)}),i.fadeOut(null,{keepLabel:!0});var h=i.__edge;h&&Io(h,{shape:od(a,r,r),style:{opacity:0}},o,function(){n.remove(h)})}function od(t,e,i){var n,o,a,r,s,l,u,h,c=t.orient;if("radial"===t.layout){s=e.rawX,u=e.rawY,l=i.rawX,h=i.rawY;var d=Uc(s,u),f=Uc(s,u+(h-u)*t.curvature),p=Uc(l,h+(u-h)*t.curvature),g=Uc(l,h);return{x1:d.x,y1:d.y,x2:g.x,y2:g.y,cpx1:f.x,cpy1:f.y,cpx2:p.x,cpy2:p.y}}return s=e.x,u=e.y,l=i.x,h=i.y,"LR"!==c&&"RL"!==c||(n=s+(l-s)*t.curvature,o=u,a=l+(s-l)*t.curvature,r=h),"TB"!==c&&"BT"!==c||(n=s,o=u+(h-u)*t.curvature,a=l,r=h+(u-h)*t.curvature),{x1:s,y1:u,x2:l,y2:h,cpx1:n,cpy1:o,cpx2:a,cpy2:r}}function ad(t,e,i){for(var n,o=[t],a=[];n=o.pop();)if(a.push(n),n.isExpand){var r=n.children;if(r.length)for(var s=0;s=0;a--)n.push(o[a])}}function sd(t,e){var i=Xc(t,e);t.layoutInfo=i;var n=t.get("layout"),o=0,a=0,r=null;"radial"===n?(o=2*Math.PI,a=Math.min(i.height,i.width)/2,r=Zc(function(t,e){return(t.parentNode===e.parentNode?1:2)/t.depth})):(o=i.width,a=i.height,r=Zc());var s=t.getData().tree.root,l=s.children[0];if(l){Fc(s),ad(l,Wc,r),s.hierNode.modifier=-l.hierNode.prelim,rd(l,Hc);var u=l,h=l,c=l;rd(l,function(t){var e=t.getLayout().x;eh.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)});var d=u===h?1:r(u,h)/2,f=d-u.getLayout().x,p=0,g=0,m=0,v=0;if("radial"===n)p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v=(t.depth-1)*g;var e=Uc(m,v);t.setLayout({x:e.x,y:e.y,rawX:m,rawY:v},!0)});else{var y=t.getOrient();"RL"===y||"LR"===y?(g=a/(h.getLayout().x+d+f),p=o/(c.depth-1||1),rd(l,function(t){v=(t.getLayout().x+f)*g,m="LR"===y?(t.depth-1)*p:o-(t.depth-1)*p,t.setLayout({x:m,y:v},!0)})):"TB"!==y&&"BT"!==y||(p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v="TB"===y?(t.depth-1)*g:a-(t.depth-1)*g,t.setLayout({x:m,y:v},!0)}))}}}function ld(t,e,i){if(t&&l(e,t.type)>=0){var n=i.getData().tree.root,o=t.targetNode;if("string"==typeof o&&(o=n.getNodeById(o)),o&&n.contains(o))return{node:o};var a=t.targetNodeId;if(null!=a&&(o=n.getNodeById(a)))return{node:o}}}function ud(t){for(var e=[];t;)(t=t.parentNode)&&e.push(t);return e.reverse()}function hd(t,e){return l(ud(t),e)>=0}function cd(t,e){for(var i=[];t;){var n=t.dataIndex;i.push({name:t.name,dataIndex:n,value:e.getRawValue(n)}),t=t.parentNode}return i.reverse(),i}function dd(t){var e=0;d(t.children,function(t){dd(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function fd(t,e){var i=e.get("color");if(i){var n;return d(t=t||[],function(t){var e=new No(t),i=e.get("color");(e.get("itemStyle.color")||i&&"none"!==i)&&(n=!0)}),n||((t[0]||(t[0]={})).color=i.slice()),t}}function pd(t){this.group=new tb,t.add(this.group)}function gd(t,e,i,n,o,a){var r=[[o?t:t-UC,e],[t+i,e],[t+i,e+n],[o?t:t-UC,e+n]];return!a&&r.splice(2,0,[t+i+UC,e+n/2]),!o&&r.push([t,e+n/2]),r}function md(t,e,i){t.eventData={componentType:"series",componentSubType:"treemap",componentIndex:e.componentIndex,seriesIndex:e.componentIndex,seriesName:e.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:i&&i.dataIndex,name:i&&i.name},treePathInfo:i&&cd(i,e)}}function vd(){var t,e=[],i={};return{add:function(t,n,o,a,r){return _(a)&&(r=a,a=0),!i[t.id]&&(i[t.id]=1,e.push({el:t,target:n,time:o,delay:a,easing:r}),!0)},done:function(e){return t=e,this},start:function(){for(var n=e.length,o=0,a=e.length;o=0;a--)null==i[a]&&(delete n[e[a]],e.pop())}function bd(t,e){var i=t.visual,n=[];w(i)?sL(i,function(t){n.push(t)}):null!=i&&n.push(i);var o={color:1,symbol:1};e||1!==n.length||o.hasOwnProperty(t.type)||(n[1]=n[0]),Ld(t,n)}function Sd(t){return{applyVisual:function(e,i,n){e=this.mapValueToVisual(e),n("color",t(i("color"),e))},_doMap:Dd([0,1])}}function Md(t){var e=this.option.visual;return e[Math.round(Bo(t,[0,1],[0,e.length-1],!0))]||{}}function Id(t){return function(e,i,n){n(t,this.mapValueToVisual(e))}}function Td(t){var e=this.option.visual;return e[this.option.loop&&t!==uL?t%e.length:t]}function Ad(){return this.option.visual[0]}function Dd(t){return{linear:function(e){return Bo(e,t,this.option.visual,!0)},category:Td,piecewise:function(e,i){var n=Cd.call(this,i);return null==n&&(n=Bo(e,t,this.option.visual,!0)),n},fixed:Ad}}function Cd(t){var e=this.option,i=e.pieceList;if(e.hasSpecialVisual){var n=i[hL.findPieceIndex(t,i)];if(n&&n.visual)return n.visual[this.type]}}function Ld(t,e){return t.visual=e,"color"===t.type&&(t.parsedVisual=f(e,function(t){return Gt(t)})),e}function kd(t,e,i){return t?e<=i:e=o.length||t===o[t.depth])&&Pd(t,Vd(r,h,t,e,g,a),i,n,o,a)})}else l=Od(h),t.setVisual("color",l)}}function Nd(t,e,i,n){var o=a({},e);return d(["color","colorAlpha","colorSaturation"],function(a){var r=t.get(a,!0);null==r&&i&&(r=i[a]),null==r&&(r=e[a]),null==r&&(r=n.get(a)),null!=r&&(o[a]=r)}),o}function Od(t){var e=Rd(t,"color");if(e){var i=Rd(t,"colorAlpha"),n=Rd(t,"colorSaturation");return n&&(e=jt(e,null,null,n)),i&&(e=Yt(e,i)),e}}function Ed(t,e){return null!=e?jt(e,null,null,t):null}function Rd(t,e){var i=t[e];if(null!=i&&"none"!==i)return i}function zd(t,e,i,n,o,a){if(a&&a.length){var r=Bd(e,"color")||null!=o.color&&"none"!==o.color&&(Bd(e,"colorAlpha")||Bd(e,"colorSaturation"));if(r){var s=e.get("visualMin"),l=e.get("visualMax"),u=i.dataExtent.slice();null!=s&&su[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:r.name,dataExtent:u,visual:r.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var d=new hL(c);return d.__drColorMappingBy=h,d}}}function Bd(t,e){var i=t.get(e);return fL(i)&&i.length?{name:e,range:i}:null}function Vd(t,e,i,n,o,r){var s=a({},e);if(o){var l=o.type,u="color"===l&&o.__drColorMappingBy,h="index"===u?n:"id"===u?r.mapIdToIndex(i.getId()):i.getValue(t.get("visualDimension"));s[l]=o.mapValueToVisual(h)}return s}function Gd(t,e,i,n){var o,a;if(!t.isRemoved()){var r=t.getLayout();o=r.width,a=r.height;var s=(f=t.getModel()).get(_L),l=f.get(wL)/2,u=Kd(f),h=Math.max(s,u),c=s-l,d=h-l,f=t.getModel();t.setLayout({borderWidth:s,upperHeight:h,upperLabelHeight:u},!0);var p=(o=mL(o-2*c,0))*(a=mL(a-c-d,0)),g=Fd(t,f,p,e,i,n);if(g.length){var m={x:c,y:d,width:o,height:a},v=vL(o,a),y=1/0,x=[];x.area=0;for(var _=0,w=g.length;_=0;l--){var u=o["asc"===n?r-l-1:l].getValue();u/i*es[1]&&(s[1]=e)})}else s=[NaN,NaN];return{sum:n,dataExtent:s}}function Ud(t,e,i){for(var n,o=0,a=1/0,r=0,s=t.length;ro&&(o=n));var l=t.area*t.area,u=e*e*i;return l?mL(u*o/l,l/(u*a)):1/0}function Xd(t,e,i,n,o){var a=e===i.width?0:1,r=1-a,s=["x","y"],l=["width","height"],u=i[s[a]],h=e?t.area/e:0;(o||h>i[l[r]])&&(h=i[l[r]]);for(var c=0,d=t.length;cXM&&(u=XM),a=s}u=0?n+=u:n-=u:p>=0?n-=u:n+=u}return n}function pf(t,e){return t.getVisual("opacity")||t.getModel().get(e)}function gf(t,e,i){var n=t.getGraphicEl(),o=pf(t,e);null!=i&&(null==o&&(o=1),o*=i),n.downplay&&n.downplay(),n.traverse(function(t){if("group"!==t.type){var e=t.lineLabelOriginalOpacity;null!=e&&null==i||(e=o),t.setStyle("opacity",e)}})}function mf(t,e){var i=pf(t,e),n=t.getGraphicEl();n.highlight&&n.highlight(),n.traverse(function(t){"group"!==t.type&&t.setStyle("opacity",i)})}function vf(t){return t instanceof Array||(t=[t,t]),t}function yf(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=t.getGraph();i.eachNode(function(t){var e=t.getModel();t.setLayout([+e.get("x"),+e.get("y")])}),xf(i)}}function xf(t){t.eachEdge(function(t){var e=t.getModel().get("lineStyle.curveness")||0,i=F(t.node1.getLayout()),n=F(t.node2.getLayout()),o=[i,n];+e&&o.push([(i[0]+n[0])/2-(i[1]-n[1])*e,(i[1]+n[1])/2-(n[0]-i[0])*e]),t.setLayout(o)})}function _f(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=e.getBoundingRect(),n=t.getData(),o=n.graph,a=0,r=n.getSum("value"),s=2*Math.PI/(r||n.count()),l=i.width/2+i.x,u=i.height/2+i.y,h=Math.min(i.width,i.height)/2;o.eachNode(function(t){var e=t.getValue("value");a+=s*(r?e:1)/2,t.setLayout([h*Math.cos(a)+l,h*Math.sin(a)+u]),a+=s*(r?e:1)/2}),n.setLayout({cx:l,cy:u}),o.eachEdge(function(t){var e,i=t.getModel().get("lineStyle.curveness")||0,n=F(t.node1.getLayout()),o=F(t.node2.getLayout()),a=(n[0]+o[0])/2,r=(n[1]+o[1])/2;+i&&(e=[l*(i*=3)+a*(1-i),u*i+r*(1-i)]),t.setLayout([n,o,e])})}}function wf(t,e,i){for(var n=i.rect,o=n.width,a=n.height,r=[n.x+o/2,n.y+a/2],s=null==i.gravity?.1:i.gravity,l=0;l0?-1:i<0?1:e?-1:1}}function Pf(t,e){return Math.min(e[1],Math.max(e[0],t))}function Nf(t,e,i){this._axesMap=R(),this._axesLayout={},this.dimensions=t.dimensions,this._rect,this._model=t,this._init(t,e,i)}function Of(t,e){return ek(ik(t,e[0]),e[1])}function Ef(t,e){var i=e.layoutLength/(e.axisCount-1);return{position:i*t,axisNameAvailableWidth:i,axisLabelShow:!0}}function Rf(t,e){var i,n,o=e.layoutLength,a=e.axisExpandWidth,r=e.axisCount,s=e.axisCollapseWidth,l=e.winInnerIndices,u=s,h=!1;return tmk}function $f(t){var e=t.length-1;return e<0&&(e=0),[t[0],t[e]]}function Jf(t,e,i,n){var o=new tb;return o.add(new yM({name:"main",style:ip(i),silent:!0,draggable:!0,cursor:"move",drift:uk(t,e,o,"nswe"),ondragend:uk(qf,e,{isEnd:!0})})),hk(n,function(i){o.add(new yM({name:i,style:{opacity:0},draggable:!0,silent:!0,invisible:!0,drift:uk(t,e,o,i),ondragend:uk(qf,e,{isEnd:!0})}))}),o}function Qf(t,e,i,n){var o=n.brushStyle.lineWidth||0,a=fk(o,vk),r=i[0][0],s=i[1][0],l=r-o/2,u=s-o/2,h=i[0][1],c=i[1][1],d=h-a+o/2,f=c-a+o/2,p=h-r,g=c-s,m=p+o,v=g+o;ep(t,e,"main",r,s,p,g),n.transformable&&(ep(t,e,"w",l,u,a,v),ep(t,e,"e",d,u,a,v),ep(t,e,"n",l,u,m,a),ep(t,e,"s",l,f,m,a),ep(t,e,"nw",l,u,a,a),ep(t,e,"ne",d,u,a,a),ep(t,e,"sw",l,f,a,a),ep(t,e,"se",d,f,a,a))}function tp(t,e){var i=e.__brushOption,n=i.transformable,o=e.childAt(0);o.useStyle(ip(i)),o.attr({silent:!n,cursor:n?"move":"default"}),hk(["w","e","n","s","se","sw","ne","nw"],function(i){var o=e.childOfName(i),a=ap(t,i);o&&o.attr({silent:!n,invisible:!n,cursor:n?_k[a]+"-resize":null})})}function ep(t,e,i,n,o,a,r){var s=e.childOfName(i);s&&s.setShape(hp(up(t,e,[[n,o],[n+a,o+r]])))}function ip(t){return r({strokeNoScale:!0},t.brushStyle)}function np(t,e,i,n){var o=[dk(t,i),dk(e,n)],a=[fk(t,i),fk(e,n)];return[[o[0],a[0]],[o[1],a[1]]]}function op(t){return Ao(t.group)}function ap(t,e){if(e.length>1)return("e"===(n=[ap(t,(e=e.split(""))[0]),ap(t,e[1])])[0]||"w"===n[0])&&n.reverse(),n.join("");var i={left:"w",right:"e",top:"n",bottom:"s"},n=Co({w:"left",e:"right",n:"top",s:"bottom"}[e],op(t));return i[n]}function rp(t,e,i,n,o,a,r,s){var l=n.__brushOption,u=t(l.range),h=lp(i,a,r);hk(o.split(""),function(t){var e=xk[t];u[e[0]][e[1]]+=h[e[0]]}),l.range=e(np(u[0][0],u[1][0],u[0][1],u[1][1])),Zf(i,n),qf(i,{isEnd:!1})}function sp(t,e,i,n,o){var a=e.__brushOption.range,r=lp(t,i,n);hk(a,function(t){t[0]+=r[0],t[1]+=r[1]}),Zf(t,e),qf(t,{isEnd:!1})}function lp(t,e,i){var n=t.group,o=n.transformCoordToLocal(e,i),a=n.transformCoordToLocal(0,0);return[o[0]-a[0],o[1]-a[1]]}function up(t,e,n){var o=jf(t,e);return o&&!0!==o?o.clipPath(n,t._transform):i(n)}function hp(t){var e=dk(t[0][0],t[1][0]),i=dk(t[0][1],t[1][1]);return{x:e,y:i,width:fk(t[0][0],t[1][0])-e,height:fk(t[0][1],t[1][1])-i}}function cp(t,e,i){if(t._brushType){var n=t._zr,o=t._covers,a=Xf(t,e,i);if(!t._dragging)for(var r=0;r0;a--)Yp(s,l*=.99,r),jp(s,o,i,n,r),tg(s,l,r),jp(s,o,i,n,r)}function Up(t,e){var i=[],n="vertical"===e?"y":"x",o=Zi(t,function(t){return t.getLayout()[n]});return o.keys.sort(function(t,e){return t-e}),d(o.keys,function(t){i.push(o.buckets.get(t))}),i}function Xp(t,e,i,n,o,a,r){var s=[];d(e,function(t){var e=t.length,i=0,l=0;d(t,function(t){i+=t.getLayout().value}),l="vertical"===r?(o-(e-1)*a)/i:(n-(e-1)*a)/i,s.push(l)}),s.sort(function(t,e){return t-e});var l=s[0];d(e,function(t){d(t,function(t,e){var i=t.getLayout().value*l;"vertical"===r?(t.setLayout({x:e},!0),t.setLayout({dx:i},!0)):(t.setLayout({y:e},!0),t.setLayout({dy:i},!0))})}),d(i,function(t){var e=+t.getValue()*l;t.setLayout({dy:e},!0)})}function jp(t,e,i,n,o){d(t,function(t){var a,r,s,l=0,u=t.length;if("vertical"===o){var h;for(t.sort(function(t,e){return t.getLayout().x-e.getLayout().x}),s=0;s0&&(h=a.getLayout().x+r,a.setLayout({x:h},!0)),l=a.getLayout().x+a.getLayout().dx+e;if((r=l-e-n)>0)for(h=a.getLayout().x-r,a.setLayout({x:h},!0),l=h,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().x+a.getLayout().dx+e-l)>0&&(h=a.getLayout().x-r,a.setLayout({x:h},!0)),l=a.getLayout().x}else{var c;for(t.sort(function(t,e){return t.getLayout().y-e.getLayout().y}),s=0;s0&&(c=a.getLayout().y+r,a.setLayout({y:c},!0)),l=a.getLayout().y+a.getLayout().dy+e;if((r=l-e-i)>0)for(c=a.getLayout().y-r,a.setLayout({y:c},!0),l=c,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().y+a.getLayout().dy+e-l)>0&&(c=a.getLayout().y-r,a.setLayout({y:c},!0)),l=a.getLayout().y}})}function Yp(t,e,i){d(t.slice().reverse(),function(t){d(t,function(t){if(t.outEdges.length){var n=Qp(t.outEdges,qp,i)/Qp(t.outEdges,Jp,i);if("vertical"===i){var o=t.getLayout().x+(n-$p(t,i))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(n-$p(t,i))*e;t.setLayout({y:a},!0)}}})})}function qp(t,e){return $p(t.node2,e)*t.getValue()}function Kp(t,e){return $p(t.node1,e)*t.getValue()}function $p(t,e){return"vertical"===e?t.getLayout().x+t.getLayout().dx/2:t.getLayout().y+t.getLayout().dy/2}function Jp(t){return t.getValue()}function Qp(t,e,i){for(var n=0,o=t.length,a=-1;++a0?"P":"N",a=n.getVisual("borderColor"+o)||n.getVisual("color"+o),r=i.getModel(Gk).getItemStyle(Wk);e.useStyle(r),e.style.fill=null,e.style.stroke=a}function fg(t,e,i,n,o){return i>n?-1:i0?t.get(o,e-1)<=n?1:-1:1}function pg(t,e){var i,n=t.getBaseAxis(),o="category"===n.type?n.getBandWidth():(i=n.getExtent(),Math.abs(i[1]-i[0])/e.count()),a=Vo(A(t.get("barMaxWidth"),o),o),r=Vo(A(t.get("barMinWidth"),1),o),s=t.get("barWidth");return null!=s?Vo(s,o):Math.max(Math.min(o/2,a),r)}function gg(t){return y(t)||(t=[+t,+t]),t}function mg(t,e){t.eachChild(function(t){t.attr({z:e.z,zlevel:e.zlevel,style:{stroke:"stroke"===e.brushType?e.color:null,fill:"fill"===e.brushType?e.color:null}})})}function vg(t,e){tb.call(this);var i=new wu(t,e),n=new tb;this.add(i),this.add(n),n.beforeUpdate=function(){this.attr(i.getScale())},this.updateData(t,e)}function yg(t){var e=t.data;e&&e[0]&&e[0][0]&&e[0][0].coord&&(t.data=f(e,function(t){var e={coords:[t[0].coord,t[1].coord]};return t[0].name&&(e.fromName=t[0].name),t[1].name&&(e.toName=t[1].name),o([e,t[0],t[1]])}))}function xg(t,e,i){tb.call(this),this.add(this.createLine(t,e,i)),this._updateEffectSymbol(t,e)}function _g(t,e,i){tb.call(this),this._createPolyline(t,e,i)}function wg(t,e,i){xg.call(this,t,e,i),this._lastFrame=0,this._lastFramePercent=0}function bg(){this.group=new tb}function Sg(t){return t instanceof Array||(t=[t,t]),t}function Mg(){var t=iw();this.canvas=t,this.blurSize=30,this.pointSize=20,this.maxOpacity=1,this.minOpacity=0,this._gradientPixels={}}function Ig(t,e,i){var n=t[1]-t[0],o=(e=f(e,function(e){return{interval:[(e.interval[0]-t[0])/n,(e.interval[1]-t[0])/n]}})).length,a=0;return function(t){for(n=a;n=0;n--){var r=e[n].interval;if(r[0]<=t&&t<=r[1]){a=n;break}}return n>=0&&n=e[0]&&t<=e[1]}}function Ag(t){var e=t.dimensions;return"lng"===e[0]&&"lat"===e[1]}function Dg(t,e,i,n){var o=t.getItemLayout(e),a=i.get("symbolRepeat"),r=i.get("symbolClip"),s=i.get("symbolPosition")||"start",l=(i.get("symbolRotate")||0)*Math.PI/180||0,u=i.get("symbolPatternSize")||2,h=i.isAnimationEnabled(),c={dataIndex:e,layout:o,itemModel:i,symbolType:t.getItemVisual(e,"symbol")||"circle",color:t.getItemVisual(e,"color"),symbolClip:r,symbolRepeat:a,symbolRepeatDirection:i.get("symbolRepeatDirection"),symbolPatternSize:u,rotation:l,animationModel:h?i:null,hoverAnimation:h&&i.get("hoverAnimation"),z2:i.getShallow("z",!0)||0};Cg(i,a,o,n,c),kg(t,e,o,a,r,c.boundingLength,c.pxSign,u,n,c),Pg(i,c.symbolScale,l,n,c);var d=c.symbolSize,f=i.get("symbolOffset");return y(f)&&(f=[Vo(f[0],d[0]),Vo(f[1],d[1])]),Ng(i,d,o,a,r,f,s,c.valueLineWidth,c.boundingLength,c.repeatCutLength,n,c),c}function Cg(t,e,i,n,o){var a,r=n.valueDim,s=t.get("symbolBoundingData"),l=n.coordSys.getOtherAxis(n.coordSys.getBaseAxis()),u=l.toGlobalCoord(l.dataToCoord(0)),h=1-+(i[r.wh]<=0);if(y(s)){var c=[Lg(l,s[0])-u,Lg(l,s[1])-u];c[1]0?1:a<0?-1:0}function Lg(t,e){return t.toGlobalCoord(t.dataToCoord(t.scale.parse(e)))}function kg(t,e,i,n,o,a,r,s,l,u){var h=l.valueDim,c=l.categoryDim,d=Math.abs(i[c.wh]),f=t.getItemVisual(e,"symbolSize");y(f)?f=f.slice():(null==f&&(f="100%"),f=[f,f]),f[c.index]=Vo(f[c.index],d),f[h.index]=Vo(f[h.index],n?d:Math.abs(a)),u.symbolSize=f,(u.symbolScale=[f[0]/s,f[1]/s])[h.index]*=(l.isHorizontal?-1:1)*r}function Pg(t,e,i,n,o){var a=t.get(cP)||0;a&&(fP.attr({scale:e.slice(),rotation:i}),fP.updateTransform(),a/=fP.getLineScale(),a*=e[n.valueDim.index]),o.valueLineWidth=a}function Ng(t,e,i,n,o,r,s,l,u,h,c,d){var f=c.categoryDim,p=c.valueDim,g=d.pxSign,m=Math.max(e[p.index]+l,0),v=m;if(n){var y=Math.abs(u),x=T(t.get("symbolMargin"),"15%")+"",_=!1;x.lastIndexOf("!")===x.length-1&&(_=!0,x=x.slice(0,x.length-1)),x=Vo(x,e[p.index]);var w=Math.max(m+2*x,0),b=_?0:2*x,S=Qo(n),M=S?n:Kg((y+b)/w);w=m+2*(x=(y-M*m)/2/(_?M:M-1)),b=_?0:2*x,S||"fixed"===n||(M=h?Kg((Math.abs(h)+b)/w):0),v=M*w-b,d.repeatTimes=M,d.symbolMargin=x}var I=g*(v/2),A=d.pathPosition=[];A[f.index]=i[f.wh]/2,A[p.index]="start"===s?I:"end"===s?u-I:u/2,r&&(A[0]+=r[0],A[1]+=r[1]);var D=d.bundlePosition=[];D[f.index]=i[f.xy],D[p.index]=i[p.xy];var C=d.barRectShape=a({},i);C[p.wh]=g*Math.max(Math.abs(i[p.wh]),Math.abs(A[p.index]+I)),C[f.wh]=i[f.wh];var L=d.clipShape={};L[f.xy]=-i[f.xy],L[f.wh]=c.ecSize[f.wh],L[p.xy]=0,L[p.wh]=i[p.wh]}function Og(t){var e=t.symbolPatternSize,i=Jl(t.symbolType,-e/2,-e/2,e,e,t.color);return i.attr({culling:!0}),"image"!==i.type&&i.setStyle({strokeNoScale:!0}),i}function Eg(t,e,i,n){function o(t){var e=l.slice(),n=i.pxSign,o=t;return("start"===i.symbolRepeatDirection?n>0:n<0)&&(o=h-1-t),e[u.index]=d*(o-h/2+.5)+l[u.index],{position:e,scale:i.symbolScale.slice(),rotation:i.rotation}}var a=t.__pictorialBundle,r=i.symbolSize,s=i.valueLineWidth,l=i.pathPosition,u=e.valueDim,h=i.repeatTimes||0,c=0,d=r[e.valueDim.index]+s+2*i.symbolMargin;for(jg(t,function(t){t.__pictorialAnimationIndex=c,t.__pictorialRepeatTimes=h,c0)],d=t.__pictorialBarRect;kh(d.style,h,a,n,e.seriesModel,o,c),fo(d,h)}function Kg(t){var e=Math.round(t);return Math.abs(t-e)<1e-4?e:Math.ceil(t)}function $g(t,e,i){this.dimension="single",this.dimensions=["single"],this._axis=null,this._rect,this._init(t,e,i),this.model=t}function Jg(t,e){e=e||{};var i=t.coordinateSystem,n=t.axis,o={},a=n.position,r=n.orient,s=i.getRect(),l=[s.x,s.x+s.width,s.y,s.y+s.height],u={horizontal:{top:l[2],bottom:l[3]},vertical:{left:l[0],right:l[1]}};o.position=["vertical"===r?u.vertical[a]:l[0],"horizontal"===r?u.horizontal[a]:l[3]];var h={horizontal:0,vertical:1};o.rotation=Math.PI/2*h[r];var c={top:-1,bottom:1,right:1,left:-1};o.labelDirection=o.tickDirection=o.nameDirection=c[a],t.get("axisTick.inside")&&(o.tickDirection=-o.tickDirection),T(e.labelInside,t.get("axisLabel.inside"))&&(o.labelDirection=-o.labelDirection);var d=e.rotate;return null==d&&(d=t.get("axisLabel.rotate")),o.labelRotation="top"===a?-d:d,o.z2=1,o}function Qg(t,e,i,n,o){var r=t.axis;if(!r.scale.isBlank()&&r.containData(e))if(t.involveSeries){var s=tm(e,t),l=s.payloadBatch,u=s.snapToValue;l[0]&&null==o.seriesIndex&&a(o,l[0]),!n&&t.snap&&r.containData(u)&&null!=u&&(e=u),i.showPointer(t,e,l,o),i.showTooltip(t,s,u)}else i.showPointer(t,e)}function tm(t,e){var i=e.axis,n=i.dim,o=t,a=[],r=Number.MAX_VALUE,s=-1;return _P(e.seriesModels,function(e,l){var u,h,c=e.getData().mapDimension(n,!0);if(e.getAxisTooltipData){var d=e.getAxisTooltipData(c,t,i);h=d.dataIndices,u=d.nestestValue}else{if(!(h=e.getData().indicesOfNearest(c[0],t,"category"===i.type?.5:null)).length)return;u=e.getData().get(c[0],h[0])}if(null!=u&&isFinite(u)){var f=t-u,p=Math.abs(f);p<=r&&((p=0&&s<0)&&(r=p,s=f,o=u,a.length=0),_P(h,function(t){a.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})}))}}),{payloadBatch:a,snapToValue:o}}function em(t,e,i,n){t[e.key]={value:i,payloadBatch:n}}function im(t,e,i,n){var o=i.payloadBatch,a=e.axis,r=a.model,s=e.axisPointerModel;if(e.triggerTooltip&&o.length){var l=e.coordSys.model,u=Ah(l),h=t.map[u];h||(h=t.map[u]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(h)),h.dataByAxis.push({axisDim:a.dim,axisIndex:r.componentIndex,axisType:r.type,axisId:r.id,value:n,valueLabelOpt:{precision:s.get("label.precision"),formatter:s.get("label.formatter")},seriesDataIndices:o.slice()})}}function nm(t,e,i){var n=i.axesInfo=[];_P(e,function(e,i){var o=e.axisPointerModel.option,a=t[i];a?(!e.useHandle&&(o.status="show"),o.value=a.value,o.seriesDataIndices=(a.payloadBatch||[]).slice()):!e.useHandle&&(o.status="hide"),"show"===o.status&&n.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:o.value})})}function om(t,e,i,n){if(!lm(e)&&t.list.length){var o=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};n({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:i.tooltipOption,position:i.position,dataIndexInside:o.dataIndexInside,dataIndex:o.dataIndex,seriesIndex:o.seriesIndex,dataByCoordSys:t.list})}else n({type:"hideTip"})}function am(t,e,i){var n=i.getZr(),o=bP(n).axisPointerLastHighlights||{},a=bP(n).axisPointerLastHighlights={};_P(t,function(t,e){var i=t.axisPointerModel.option;"show"===i.status&&_P(i.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;a[e]=t})});var r=[],s=[];d(o,function(t,e){!a[e]&&s.push(t)}),d(a,function(t,e){!o[e]&&r.push(t)}),s.length&&i.dispatchAction({type:"downplay",escapeConnect:!0,batch:s}),r.length&&i.dispatchAction({type:"highlight",escapeConnect:!0,batch:r})}function rm(t,e){for(var i=0;i<(t||[]).length;i++){var n=t[i];if(e.axis.dim===n.axisDim&&e.axis.model.componentIndex===n.axisIndex)return n}}function sm(t){var e=t.axis.model,i={},n=i.axisDim=t.axis.dim;return i.axisIndex=i[n+"AxisIndex"]=e.componentIndex,i.axisName=i[n+"AxisName"]=e.name,i.axisId=i[n+"AxisId"]=e.id,i}function lm(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function um(t,e,i){if(!U_.node){var n=e.getZr();SP(n).records||(SP(n).records={}),hm(n,e),(SP(n).records[t]||(SP(n).records[t]={})).handler=i}}function hm(t,e){function i(i,n){t.on(i,function(i){var o=pm(e);MP(SP(t).records,function(t){t&&n(t,i,o.dispatchAction)}),cm(o.pendings,e)})}SP(t).initialized||(SP(t).initialized=!0,i("click",v(fm,"click")),i("mousemove",v(fm,"mousemove")),i("globalout",dm))}function cm(t,e){var i,n=t.showTip.length,o=t.hideTip.length;n?i=t.showTip[n-1]:o&&(i=t.hideTip[o-1]),i&&(i.dispatchAction=null,e.dispatchAction(i))}function dm(t,e,i){t.handler("leave",null,i)}function fm(t,e,i,n){e.handler(t,i,n)}function pm(t){var e={showTip:[],hideTip:[]},i=function(n){var o=e[n.type];o?o.push(n):(n.dispatchAction=i,t.dispatchAction(n))};return{dispatchAction:i,pendings:e}}function gm(t,e){if(!U_.node){var i=e.getZr();(SP(i).records||{})[t]&&(SP(i).records[t]=null)}}function mm(){}function vm(t,e,i,n){ym(TP(i).lastProp,n)||(TP(i).lastProp=n,e?Io(i,n,t):(i.stopAnimation(),i.attr(n)))}function ym(t,e){if(w(t)&&w(e)){var i=!0;return d(e,function(e,n){i=i&&ym(t[n],e)}),!!i}return t===e}function xm(t,e){t[e.get("label.show")?"show":"hide"]()}function _m(t){return{position:t.position.slice(),rotation:t.rotation||0}}function wm(t,e,i){var n=e.get("z"),o=e.get("zlevel");t&&t.traverse(function(t){"group"!==t.type&&(null!=n&&(t.z=n),null!=o&&(t.zlevel=o),t.silent=i)})}function bm(t){var e,i=t.get("type"),n=t.getModel(i+"Style");return"line"===i?(e=n.getLineStyle()).fill=null:"shadow"===i&&((e=n.getAreaStyle()).stroke=null),e}function Sm(t,e,i,n,o){var a=Im(i.get("value"),e.axis,e.ecModel,i.get("seriesDataIndices"),{precision:i.get("label.precision"),formatter:i.get("label.formatter")}),r=i.getModel("label"),s=qM(r.get("padding")||0),l=r.getFont(),u=ke(a,l),h=o.position,c=u.width+s[1]+s[3],d=u.height+s[0]+s[2],f=o.align;"right"===f&&(h[0]-=c),"center"===f&&(h[0]-=c/2);var p=o.verticalAlign;"bottom"===p&&(h[1]-=d),"middle"===p&&(h[1]-=d/2),Mm(h,c,d,n);var g=r.get("backgroundColor");g&&"auto"!==g||(g=e.get("axisLine.lineStyle.color")),t.label={shape:{x:0,y:0,width:c,height:d,r:r.get("borderRadius")},position:h.slice(),style:{text:a,textFont:l,textFill:r.getTextColor(),textPosition:"inside",fill:g,stroke:r.get("borderColor")||"transparent",lineWidth:r.get("borderWidth")||0,shadowBlur:r.get("shadowBlur"),shadowColor:r.get("shadowColor"),shadowOffsetX:r.get("shadowOffsetX"),shadowOffsetY:r.get("shadowOffsetY")},z2:10}}function Mm(t,e,i,n){var o=n.getWidth(),a=n.getHeight();t[0]=Math.min(t[0]+e,o)-e,t[1]=Math.min(t[1]+i,a)-i,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}function Im(t,e,i,n,o){t=e.scale.parse(t);var a=e.scale.getLabel(t,{precision:o.precision}),r=o.formatter;if(r){var s={value:Xl(e,t),seriesData:[]};d(n,function(t){var e=i.getSeriesByIndex(t.seriesIndex),n=t.dataIndexInside,o=e&&e.getDataParams(n);o&&s.seriesData.push(o)}),_(r)?a=r.replace("{value}",a):x(r)&&(a=r(s))}return a}function Tm(t,e,i){var n=xt();return Mt(n,n,i.rotation),St(n,n,i.position),Do([t.dataToCoord(e),(i.labelOffset||0)+(i.labelDirection||1)*(i.labelMargin||0)],n)}function Am(t,e,i,n,o,a){var r=FD.innerTextLayout(i.rotation,0,i.labelDirection);i.labelMargin=o.get("label.margin"),Sm(e,n,o,a,{position:Tm(n.axis,t,i),align:r.textAlign,verticalAlign:r.textVerticalAlign})}function Dm(t,e,i){return i=i||0,{x1:t[i],y1:t[1-i],x2:e[i],y2:e[1-i]}}function Cm(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}function Lm(t,e,i,n,o,a){return{cx:t,cy:e,r0:i,r:n,startAngle:o,endAngle:a,clockwise:!0}}function km(t,e){var i={};return i[e.dim+"AxisIndex"]=e.index,t.getCartesian(i)}function Pm(t){return"x"===t.dim?0:1}function Nm(t){return t.isHorizontal()?0:1}function Om(t,e){var i=t.getRect();return[i[kP[e]],i[kP[e]]+i[PP[e]]]}function Em(t,e,i){var n=new yM({shape:{x:t.x-10,y:t.y-10,width:0,height:t.height+20}});return To(n,{shape:{width:t.width+20,height:t.height+20}},e,i),n}function Rm(t,e,i){if(t.count())for(var n,o=e.coordinateSystem,a=e.getLayerSeries(),r=t.mapDimension("single"),s=t.mapDimension("value"),l=f(a,function(e){return f(e.indices,function(e){var i=o.dataToPoint(t.get(r,e));return i[1]=t.get(s,e),i})}),u=zm(l),h=u.y0,c=i/u.max,d=a.length,p=a[0].indices.length,g=0;ga&&(a=u),n.push(u)}for(var h=0;ha&&(a=d)}return r.y0=o,r.max=a,r}function Bm(t){var e=0;d(t.children,function(t){Bm(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function Vm(t,e,i){function n(){r.ignore=r.hoverIgnore}function o(){r.ignore=r.normalIgnore}tb.call(this);var a=new hM({z2:zP});a.seriesIndex=e.seriesIndex;var r=new rM({z2:BP,silent:t.getModel("label").get("silent")});this.add(a),this.add(r),this.updateData(!0,t,"normal",e,i),this.on("emphasis",n).on("normal",o).on("mouseover",n).on("mouseout",o)}function Gm(t,e,i){var n=t.getVisual("color"),o=t.getVisual("visualMeta");o&&0!==o.length||(n=null);var a=t.getModel("itemStyle").get("color");if(a)return a;if(n)return n;if(0===t.depth)return i.option.color[0];var r=i.option.color.length;return a=i.option.color[Fm(t)%r]}function Fm(t){for(var e=t;e.depth>1;)e=e.parentNode;return l(t.getAncestors()[0].children,e)}function Wm(t,e,i){return i!==RP.NONE&&(i===RP.SELF?t===e:i===RP.ANCESTOR?t===e||t.isAncestorOf(e):t===e||t.isDescendantOf(e))}function Hm(t,e,i){e.getData().setItemVisual(t.dataIndex,"color",i)}function Zm(t,e){var i=t.children||[];t.children=Um(i,e),i.length&&d(t.children,function(t){Zm(t,e)})}function Um(t,e){if("function"==typeof e)return t.sort(e);var i="asc"===e;return t.sort(function(t,e){var n=(t.getValue()-e.getValue())*(i?1:-1);return 0===n?(t.dataIndex-e.dataIndex)*(i?-1:1):n})}function Xm(t,e){return e=e||[0,0],f(["x","y"],function(i,n){var o=this.getAxis(i),a=e[n],r=t[n]/2;return"category"===o.type?o.getBandWidth():Math.abs(o.dataToCoord(a-r)-o.dataToCoord(a+r))},this)}function jm(t,e){return e=e||[0,0],f([0,1],function(i){var n=e[i],o=t[i]/2,a=[],r=[];return a[i]=n-o,r[i]=n+o,a[1-i]=r[1-i]=e[1-i],Math.abs(this.dataToPoint(a)[i]-this.dataToPoint(r)[i])},this)}function Ym(t,e){var i=this.getAxis(),n=e instanceof Array?e[0]:e,o=(t instanceof Array?t[0]:t)/2;return"category"===i.type?i.getBandWidth():Math.abs(i.dataToCoord(n-o)-i.dataToCoord(n+o))}function qm(t,e){return f(["Radius","Angle"],function(i,n){var o=this["get"+i+"Axis"](),a=e[n],r=t[n]/2,s="dataTo"+i,l="category"===o.type?o.getBandWidth():Math.abs(o[s](a-r)-o[s](a+r));return"Angle"===i&&(l=l*Math.PI/180),l},this)}function Km(t){var e,i=t.type;if("path"===i){var n=t.shape,o=null!=n.width&&null!=n.height?{x:n.x||0,y:n.y||0,width:n.width,height:n.height}:null,a=lv(n);(e=Xn(a,null,o,n.layout||"center")).__customPathData=a}else"image"===i?(e=new fi({})).__customImagePath=t.style.image:"text"===i?(e=new rM({})).__customText=t.style.text:e=new(0,zM[i.charAt(0).toUpperCase()+i.slice(1)]);return e.__customGraphicType=i,e.name=t.name,e}function $m(t,e,n,o,a,r,s){var l={},u=n.style||{};if(n.shape&&(l.shape=i(n.shape)),n.position&&(l.position=n.position.slice()),n.scale&&(l.scale=n.scale.slice()),n.origin&&(l.origin=n.origin.slice()),n.rotation&&(l.rotation=n.rotation),"image"===t.type&&n.style){h=l.style={};d(["x","y","width","height"],function(e){Jm(e,h,u,t.style,r)})}if("text"===t.type&&n.style){var h=l.style={};d(["x","y"],function(e){Jm(e,h,u,t.style,r)}),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke)}if("group"!==t.type&&(t.useStyle(u),r)){t.style.opacity=0;var c=u.opacity;null==c&&(c=1),To(t,{style:{opacity:c}},o,e)}r?t.attr(l):Io(t,l,o,e),n.hasOwnProperty("z2")&&t.attr("z2",n.z2||0),n.hasOwnProperty("silent")&&t.attr("silent",n.silent),n.hasOwnProperty("invisible")&&t.attr("invisible",n.invisible),n.hasOwnProperty("ignore")&&t.attr("ignore",n.ignore),n.hasOwnProperty("info")&&t.attr("info",n.info);var f=n.styleEmphasis,p=!1===f;t.__cusHasEmphStl&&null==f||!t.__cusHasEmphStl&&p||(ro(t,f),t.__cusHasEmphStl=!p),s&&po(t,!p)}function Jm(t,e,i,n,o){null==i[t]||o||(e[t]=i[t],i[t]=n[t])}function Qm(t,e,i,n){function o(t){null==t&&(t=h),v&&(c=e.getItemModel(t),d=c.getModel(UP),f=c.getModel(XP),p=e.getItemVisual(t,"color"),v=!1)}var s=t.get("renderItem"),l=t.coordinateSystem,u={};l&&(u=l.prepareCustoms?l.prepareCustoms():YP[l.type](l));var h,c,d,f,p,g=r({getWidth:n.getWidth,getHeight:n.getHeight,getZr:n.getZr,getDevicePixelRatio:n.getDevicePixelRatio,value:function(t,i){return null==i&&(i=h),e.get(e.getDimension(t||0),i)},style:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(HP).getItemStyle();null!=p&&(r.fill=p);var s=e.getItemVisual(n,"opacity");return null!=s&&(r.opacity=s),mo(r,d,null,{autoColor:p,isRectText:!0}),r.text=d.getShallow("show")?A(t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},styleEmphasis:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(ZP).getItemStyle();return mo(r,f,null,{isRectText:!0},!0),r.text=f.getShallow("show")?D(t.getFormattedLabel(n,"emphasis"),t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},visual:function(t,i){return null==i&&(i=h),e.getItemVisual(i,t)},barLayout:function(t){if(l.getBaseAxis)return Ll(r({axis:l.getBaseAxis()},t),n)},currentSeriesIndices:function(){return i.getCurrentSeriesIndices()},font:function(t){return So(t,i)}},u.api||{}),m={context:{},seriesId:t.id,seriesName:t.name,seriesIndex:t.seriesIndex,coordSys:u.coordSys,dataInsideLength:e.count(),encode:tv(t.getData())},v=!0;return function(t,i){return h=t,v=!0,s&&s(r({dataIndexInside:t,dataIndex:e.getRawIndex(t),actionType:i?i.type:null},m),g)}}function tv(t){var e={};return d(t.dimensions,function(i,n){var o=t.getDimensionInfo(i);if(!o.isExtraCoord){var a=o.coordDim;(e[a]=e[a]||[])[o.coordDimIndex]=n}}),e}function ev(t,e,i,n,o,a){return(t=iv(t,e,i,n,o,a,!0))&&a.setItemGraphicEl(e,t),t}function iv(t,e,i,n,o,a,r){var s=!i,l=(i=i||{}).type,u=i.shape,h=i.style;if(t&&(s||null!=l&&l!==t.__customGraphicType||"path"===l&&uv(u)&&lv(u)!==t.__customPathData||"image"===l&&hv(h,"image")&&h.image!==t.__customImagePath||"text"===l&&hv(u,"text")&&h.text!==t.__customText)&&(o.remove(t),t=null),!s){var c=!t;return!t&&(t=Km(i)),$m(t,e,i,n,a,c,r),"group"===l&&nv(t,e,i,n,a),o.add(t),t}}function nv(t,e,i,n,o){var a=i.children,r=a?a.length:0,s=i.$mergeChildren,l="byName"===s||i.diffChildrenByName,u=!1===s;if(r||l||u)if(l)ov({oldChildren:t.children()||[],newChildren:a||[],dataIndex:e,animatableModel:n,group:t,data:o});else{u&&t.removeAll();for(var h=0;hn?t-=l+a:t+=a),null!=r&&(e+u+r>o?e-=u+r:e+=r),[t,e]}function Ov(t,e,i,n,o){var a=i.getOuterSize(),r=a.width,s=a.height;return t=Math.min(t+r,n)-r,e=Math.min(e+s,o)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}function Ev(t,e,i){var n=i[0],o=i[1],a=0,r=0,s=e.width,l=e.height;switch(t){case"inside":a=e.x+s/2-n/2,r=e.y+l/2-o/2;break;case"top":a=e.x+s/2-n/2,r=e.y-o-5;break;case"bottom":a=e.x+s/2-n/2,r=e.y+l+5;break;case"left":a=e.x-n-5,r=e.y+l/2-o/2;break;case"right":a=e.x+s+5,r=e.y+l/2-o/2}return[a,r]}function Rv(t){return"center"===t||"middle"===t}function zv(t){return t.get("stack")||"__ec_stack_"+t.seriesIndex}function Bv(t){return t.dim}function Vv(t,e){var i={};d(t,function(t,e){var n=t.getData(),o=t.coordinateSystem.getBaseAxis(),a=o.getExtent(),r="category"===o.type?o.getBandWidth():Math.abs(a[1]-a[0])/n.count(),s=i[Bv(o)]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},l=s.stacks;i[Bv(o)]=s;var u=zv(t);l[u]||s.autoWidthCount++,l[u]=l[u]||{width:0,maxWidth:0};var h=Vo(t.get("barWidth"),r),c=Vo(t.get("barMaxWidth"),r),d=t.get("barGap"),f=t.get("barCategoryGap");h&&!l[u].width&&(h=Math.min(s.remainedWidth,h),l[u].width=h,s.remainedWidth-=h),c&&(l[u].maxWidth=c),null!=d&&(s.gap=d),null!=f&&(s.categoryGap=f)});var n={};return d(i,function(t,e){n[e]={};var i=t.stacks,o=t.bandWidth,a=Vo(t.categoryGap,o),r=Vo(t.gap,1),s=t.remainedWidth,l=t.autoWidthCount,u=(s-a)/(l+(l-1)*r);u=Math.max(u,0),d(i,function(t,e){var i=t.maxWidth;i&&ie[0]&&(e=e.slice().reverse());var n=t.coordToPoint([e[0],i]),o=t.coordToPoint([e[1],i]);return{x1:n[0],y1:n[1],x2:o[0],y2:o[1]}}function jv(t){return t.getRadiusAxis().inverse?0:1}function Yv(t){var e=t[0],i=t[t.length-1];e&&i&&Math.abs(Math.abs(e.coord-i.coord)-360)<1e-4&&t.pop()}function qv(t,e,i){return{position:[t.cx,t.cy],rotation:i/180*Math.PI,labelDirection:-1,tickDirection:-1,nameDirection:1,labelRotate:e.getModel("axisLabel").get("rotate"),z2:1}}function Kv(t,e,i,n,o){var a=e.axis,r=a.dataToCoord(t),s=n.getAngleAxis().getExtent()[0];s=s/180*Math.PI;var l,u,h,c=n.getRadiusAxis().getExtent();if("radius"===a.dim){var d=xt();Mt(d,d,s),St(d,d,[n.cx,n.cy]),l=Do([r,-o],d);var f=e.getModel("axisLabel").get("rotate")||0,p=FD.innerTextLayout(s,f*Math.PI/180,-1);u=p.textAlign,h=p.textVerticalAlign}else{var g=c[1];l=n.coordToPoint([g+o,r]);var m=n.cx,v=n.cy;u=Math.abs(l[0]-m)/g<.3?"center":l[0]>m?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}function $v(t,e){e.update="updateView",Es(e,function(e,i){var n={};return i.eachComponent({mainType:"geo",query:e},function(i){i[t](e.name),d(i.coordinateSystem.regions,function(t){n[t.name]=i.isSelected(t.name)||!1})}),{selected:n,name:e.name}})}function Jv(t){var e={};d(t,function(t){e[t]=1}),t.length=0,d(e,function(e,i){t.push(i)})}function Qv(t){if(t)for(var e in t)if(t.hasOwnProperty(e))return!0}function ty(t,e,n){function o(){var t=function(){};return t.prototype.__hidden=t.prototype,new t}var a={};return MN(e,function(e){var r=a[e]=o();MN(t[e],function(t,o){if(hL.isValidType(o)){var a={type:o,visual:t};n&&n(a,e),r[o]=new hL(a),"opacity"===o&&((a=i(a)).type="colorAlpha",r.__hidden.__alphaForOpacity=new hL(a))}})}),a}function ey(t,e,n){var o;d(n,function(t){e.hasOwnProperty(t)&&Qv(e[t])&&(o=!0)}),o&&d(n,function(n){e.hasOwnProperty(n)&&Qv(e[n])?t[n]=i(e[n]):delete t[n]})}function iy(t,e,i,n,o,a){function r(t){return i.getItemVisual(h,t)}function s(t,e){i.setItemVisual(h,t,e)}function l(t,l){h=null==a?t:l;var c=i.getRawDataItem(h);if(!c||!1!==c.visualMap)for(var d=n.call(o,t),f=e[d],p=u[d],g=0,m=p.length;g1)return!1;var h=uy(i-t,o-t,n-e,a-e)/l;return!(h<0||h>1)}function ly(t){return t<=1e-6&&t>=-1e-6}function uy(t,e,i,n){return t*n-e*i}function hy(t,e,i){var n=this._targetInfoList=[],o={},a=dy(e,t);TN(PN,function(t,e){(!i||!i.include||AN(i.include,e)>=0)&&t(a,n,o)})}function cy(t){return t[0]>t[1]&&t.reverse(),t}function dy(t,e){return Vi(t,e,{includeMainTypes:LN})}function fy(t,e,i,n){var o=i.getAxis(["x","y"][t]),a=cy(f([0,1],function(t){return e?o.coordToData(o.toLocalCoord(n[t])):o.toGlobalCoord(o.dataToCoord(n[t]))})),r=[];return r[t]=a,r[1-t]=[NaN,NaN],{values:a,xyMinMax:r}}function py(t,e,i,n){return[e[0]-n[t]*i[0],e[1]-n[t]*i[1]]}function gy(t,e){var i=my(t),n=my(e),o=[i[0]/n[0],i[1]/n[1]];return isNaN(o[0])&&(o[0]=1),isNaN(o[1])&&(o[1]=1),o}function my(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}function vy(t,e,i,n,o){if(o){var a=t.getZr();a[VN]||(a[BN]||(a[BN]=yy),Nr(a,BN,i,e)(t,n))}}function yy(t,e){if(!t.isDisposed()){var i=t.getZr();i[VN]=!0,t.dispatchAction({type:"brushSelect",batch:e}),i[VN]=!1}}function xy(t,e,i,n){for(var o=0,a=e.length;o=0}function Ny(t,e,i){function n(t,e){return l(e.nodes,t)>=0}function o(t,n){var o=!1;return e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]&&(o=!0)})}),o}function a(t,n){n.nodes.push(t),e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]=!0})})}return function(i){var r={nodes:[],records:{}};if(e(function(t){r.records[t.name]={}}),!i)return r;a(i,r);var s;do{s=!1,t(function(t){!n(t,r)&&o(t,r)&&(a(t,r),s=!0)})}while(s);return r}}function Oy(t,e,i){var n=[1/0,-1/0];return $N(i,function(t){var i=t.getData();i&&$N(i.mapDimension(e,!0),function(t){var e=i.getApproximateExtent(t);e[0]n[1]&&(n[1]=e[1])})}),n[1]0?0:NaN);var r=i.getMax(!0);return null!=r&&"dataMax"!==r&&"function"!=typeof r?e[1]=r:o&&(e[1]=a>0?a-1:NaN),i.get("scale",!0)||(e[0]>0&&(e[0]=0),e[1]<0&&(e[1]=0)),e}function Ry(t,e){var i=t.getAxisModel(),n=t._percentWindow,o=t._valueWindow;if(n){var a=Zo(o,[0,500]);a=Math.min(a,20);var r=e||0===n[0]&&100===n[1];i.setRange(r?null:+o[0].toFixed(a),r?null:+o[1].toFixed(a))}}function zy(t){var e=t._minMaxSpan={},i=t._dataZoomModel;$N(["min","max"],function(n){e[n+"Span"]=i.get(n+"Span");var o=i.get(n+"ValueSpan");if(null!=o&&(e[n+"ValueSpan"]=o,null!=(o=t.getAxisModel().axis.scale.parse(o)))){var a=t._dataExtent;e[n+"Span"]=Bo(a[0]+o,a,[0,100],!0)}})}function By(t){var e={};return tO(["start","end","startValue","endValue","throttle"],function(i){t.hasOwnProperty(i)&&(e[i]=t[i])}),e}function Vy(t,e){var i=t._rangePropMode,n=t.get("rangeMode");tO([["start","startValue"],["end","endValue"]],function(t,o){var a=null!=e[t[0]],r=null!=e[t[1]];a&&!r?i[o]="percent":!a&&r?i[o]="value":n?i[o]=n[o]:a&&(i[o]="percent")})}function Gy(t){return{x:"y",y:"x",radius:"angle",angle:"radius"}[t]}function Fy(t){return"vertical"===t?"ns-resize":"ew-resize"}function Wy(t,e){var i=Uy(t),n=e.dataZoomId,o=e.coordId;d(i,function(t,i){var a=t.dataZoomInfos;a[n]&&l(e.allCoordIds,o)<0&&(delete a[n],t.count--)}),jy(i);var a=i[o];a||((a=i[o]={coordId:o,dataZoomInfos:{},count:0}).controller=Xy(t,a),a.dispatchAction=v(Yy,t)),!a.dataZoomInfos[n]&&a.count++,a.dataZoomInfos[n]=e;var r=qy(a.dataZoomInfos);a.controller.enable(r.controlType,r.opt),a.controller.setPointerChecker(e.containsPoint),Nr(a,"dispatchAction",e.dataZoomModel.get("throttle",!0),"fixRate")}function Hy(t,e){var i=Uy(t);d(i,function(t){t.controller.dispose();var i=t.dataZoomInfos;i[e]&&(delete i[e],t.count--)}),jy(i)}function Zy(t){return t.type+"\0_"+t.id}function Uy(t){var e=t.getZr();return e[fO]||(e[fO]={})}function Xy(t,e){var i=new oc(t.getZr());return d(["pan","zoom","scrollMove"],function(t){i.on(t,function(i){var n=[];d(e.dataZoomInfos,function(o){if(i.isAvailableBehavior(o.dataZoomModel.option)){var a=(o.getRange||{})[t],r=a&&a(e.controller,i);!o.dataZoomModel.get("disabled",!0)&&r&&n.push({dataZoomId:o.dataZoomId,start:r[0],end:r[1]})}}),n.length&&e.dispatchAction(n)})}),i}function jy(t){d(t,function(e,i){e.count||(e.controller.dispose(),delete t[i])})}function Yy(t,e){t.dispatchAction({type:"dataZoom",batch:e})}function qy(t){var e,i={type_true:2,type_move:1,type_false:0,type_undefined:-1},n=!0;return d(t,function(t){var o=t.dataZoomModel,a=!o.get("disabled",!0)&&(!o.get("zoomLock",!0)||"move");i["type_"+a]>i["type_"+e]&&(e=a),n&=o.get("preventDefaultMouseMove",!0)}),{controlType:e,opt:{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!0,preventDefaultMouseMove:!!n}}}function Ky(t){return function(e,i,n,o){var a=this._range,r=a.slice(),s=e.axisModels[0];if(s){var l=t(r,s,e,i,n,o);return QL(l,r,[0,100],"all"),this._range=r,a[0]!==r[0]||a[1]!==r[1]?r:void 0}}}function $y(t,e){return t&&t.hasOwnProperty&&t.hasOwnProperty(e)}function Jy(t,e,i,n){for(var o=e.targetVisuals[n],a=hL.prepareVisualTypes(o),r={color:t.getData().getVisual("color")},s=0,l=a.length;s=0&&(r[a]=+r[a].toFixed(h)),r}function fx(t,e){var n=t.getData(),o=t.coordinateSystem;if(e&&!cx(e)&&!y(e.coord)&&o){var a=o.dimensions,r=px(e,n,o,t);if((e=i(e)).type&&YO[e.type]&&r.baseAxis&&r.valueAxis){var s=XO(a,r.baseAxis.dim),l=XO(a,r.valueAxis.dim);e.coord=YO[e.type](n,r.baseDataDim,r.valueDataDim,s,l),e.value=e.coord[l]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)YO[u[h]]&&(u[h]=yx(n,n.mapDimension(a[h]),u[h]));e.coord=u}}return e}function px(t,e,i,n){var o={};return null!=t.valueIndex||null!=t.valueDim?(o.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,o.valueAxis=i.getAxis(gx(n,o.valueDataDim)),o.baseAxis=i.getOtherAxis(o.valueAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim)):(o.baseAxis=n.getBaseAxis(),o.valueAxis=i.getOtherAxis(o.baseAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim),o.valueDataDim=e.mapDimension(o.valueAxis.dim)),o}function gx(t,e){var i=t.getData(),n=i.dimensions;e=i.getDimension(e);for(var o=0;o=0)return!0}function Yx(t){for(var e=t.split(/\n+/g),i=[],n=f(Xx(e.shift()).split(pE),function(t){return{name:t,data:[]}}),o=0;o=0&&!i[o][n];o--);if(o<0){var a=t.queryComponents({mainType:"dataZoom",subType:"select",id:n})[0];if(a){var r=a.getPercentRange();i[0][n]={dataZoomId:n,start:r[0],end:r[1]}}}}),i.push(e)}function t_(t){var e=n_(t),i=e[e.length-1];e.length>1&&e.pop();var n={};return gE(i,function(t,i){for(var o=e.length-1;o>=0;o--)if(t=e[o][i]){n[i]=t;break}}),n}function e_(t){t[mE]=null}function i_(t){return n_(t).length}function n_(t){var e=t[mE];return e||(e=t[mE]=[{}]),e}function o_(t,e,i){(this._brushController=new zf(i.getZr())).on("brush",m(this._onBrush,this)).mount(),this._isZoomActive}function a_(t){var e={};return d(["xAxisIndex","yAxisIndex"],function(i){e[i]=t[i],null==e[i]&&(e[i]="all"),(!1===e[i]||"none"===e[i])&&(e[i]=[])}),e}function r_(t,e){t.setIconStatus("back",i_(e)>1?"emphasis":"normal")}function s_(t,e,i,n,o){var a=i._isZoomActive;n&&"takeGlobalCursor"===n.type&&(a="dataZoomSelect"===n.key&&n.dataZoomSelectActive),i._isZoomActive=a,t.setIconStatus("zoom",a?"emphasis":"normal");var r=new hy(a_(t.option),e,{include:["grid"]});i._brushController.setPanels(r.makePanelOpts(o,function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"})).enableBrush(!!a&&{brushType:"auto",brushStyle:{lineWidth:0,fill:"rgba(0,0,0,0.2)"}})}function l_(t){this.model=t}function u_(t){return SE(t)}function h_(){if(!TE&&AE){TE=!0;var t=AE.styleSheets;t.length<31?AE.createStyleSheet().addRule(".zrvml","behavior:url(#default#VML)"):t[0].addRule(".zrvml","behavior:url(#default#VML)")}}function c_(t){return parseInt(t,10)}function d_(t,e){h_(),this.root=t,this.storage=e;var i=document.createElement("div"),n=document.createElement("div");i.style.cssText="display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;",n.style.cssText="position:absolute;left:0;top:0;",t.appendChild(i),this._vmlRoot=n,this._vmlViewport=i,this.resize();var o=e.delFromStorage,a=e.addToStorage;e.delFromStorage=function(t){o.call(e,t),t&&t.onRemove&&t.onRemove(n)},e.addToStorage=function(t){t.onAdd&&t.onAdd(n),a.call(e,t)},this._firstPaint=!0}function f_(t){return function(){Yw('In IE8.0 VML mode painter not support method "'+t+'"')}}function p_(t){return document.createElementNS(sR,t)}function g_(t){return cR(1e4*t)/1e4}function m_(t){return t-vR}function v_(t,e){var i=e?t.textFill:t.fill;return null!=i&&i!==hR}function y_(t,e){var i=e?t.textStroke:t.stroke;return null!=i&&i!==hR}function x_(t,e){e&&__(t,"transform","matrix("+uR.call(e,",")+")")}function __(t,e,i){(!i||"linear"!==i.type&&"radial"!==i.type)&&t.setAttribute(e,i)}function w_(t,e,i){t.setAttributeNS("http://www.w3.org/1999/xlink",e,i)}function b_(t,e,i,n){if(v_(e,i)){var o=i?e.textFill:e.fill;o="transparent"===o?hR:o,"none"!==t.getAttribute("clip-path")&&o===hR&&(o="rgba(0, 0, 0, 0.002)"),__(t,"fill",o),__(t,"fill-opacity",null!=e.fillOpacity?e.fillOpacity*e.opacity:e.opacity)}else __(t,"fill",hR);if(y_(e,i)){var a=i?e.textStroke:e.stroke;__(t,"stroke",a="transparent"===a?hR:a),__(t,"stroke-width",(i?e.textStrokeWidth:e.lineWidth)/(!i&&e.strokeNoScale?n.getLineScale():1)),__(t,"paint-order",i?"stroke":"fill"),__(t,"stroke-opacity",null!=e.strokeOpacity?e.strokeOpacity:e.opacity),e.lineDash?(__(t,"stroke-dasharray",e.lineDash.join(",")),__(t,"stroke-dashoffset",cR(e.lineDashOffset||0))):__(t,"stroke-dasharray",""),e.lineCap&&__(t,"stroke-linecap",e.lineCap),e.lineJoin&&__(t,"stroke-linejoin",e.lineJoin),e.miterLimit&&__(t,"stroke-miterlimit",e.miterLimit)}else __(t,"stroke",hR)}function S_(t){for(var e=[],i=t.data,n=t.len(),o=0;o=gR||!m_(g)&&(d>-pR&&d<0||d>pR)==!!p;var y=g_(s+u*fR(c)),x=g_(l+h*dR(c));m&&(d=p?gR-1e-4:1e-4-gR,v=!0,9===o&&e.push("M",y,x));var _=g_(s+u*fR(c+d)),w=g_(l+h*dR(c+d));e.push("A",g_(u),g_(h),cR(f*mR),+v,+p,_,w);break;case lR.Z:a="Z";break;case lR.R:var _=g_(i[o++]),w=g_(i[o++]),b=g_(i[o++]),S=g_(i[o++]);e.push("M",_,w,"L",_+b,w,"L",_+b,w+S,"L",_,w+S,"L",_,w)}a&&e.push(a);for(var M=0;M=11),domSupported:"undefined"!=typeof document}}(navigator.userAgent),X_={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},j_={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},Y_=Object.prototype.toString,q_=Array.prototype,K_=q_.forEach,$_=q_.filter,J_=q_.slice,Q_=q_.map,tw=q_.reduce,ew={},iw=function(){return ew.createCanvas()};ew.createCanvas=function(){return document.createElement("canvas")};var nw,ow="__ec_primitive__";E.prototype={constructor:E,get:function(t){return this.data.hasOwnProperty(t)?this.data[t]:null},set:function(t,e){return this.data[t]=e},each:function(t,e){void 0!==e&&(t=m(t,e));for(var i in this.data)this.data.hasOwnProperty(i)&&t(this.data[i],i)},removeKey:function(t){delete this.data[t]}};var aw=(Object.freeze||Object)({$override:e,clone:i,merge:n,mergeAll:o,extend:a,defaults:r,createCanvas:iw,getContext:s,indexOf:l,inherits:u,mixin:h,isArrayLike:c,each:d,map:f,reduce:p,filter:g,find:function(t,e,i){if(t&&e)for(var n=0,o=t.length;n3&&(n=dw.call(n,1));for(var a=e.length,r=0;r4&&(n=dw.call(n,1,n.length-1));for(var a=n[n.length-1],r=e.length,s=0;s1&&n&&n.length>1){var a=ft(n)/ft(o);!isFinite(a)&&(a=1),e.pinchScale=a;var r=pt(n);return e.pinchX=r[0],e.pinchY=r[1],{type:"pinch",target:t[0].target,event:e}}}}},xw="silent";vt.prototype.dispose=function(){};var _w=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],ww=function(t,e,i,n){fw.call(this),this.storage=t,this.painter=e,this.painterRoot=n,i=i||new vt,this.proxy=null,this._hovered={},this._lastTouchMoment,this._lastX,this._lastY,this._gestureMgr,it.call(this),this.setHandlerProxy(i)};ww.prototype={constructor:ww,setHandlerProxy:function(t){this.proxy&&this.proxy.dispose(),t&&(d(_w,function(e){t.on&&t.on(e,this[e],this)},this),t.handler=this),this.proxy=t},mousemove:function(t){var e=t.zrX,i=t.zrY,n=this._hovered,o=n.target;o&&!o.__zr&&(o=(n=this.findHover(n.x,n.y)).target);var a=this._hovered=this.findHover(e,i),r=a.target,s=this.proxy;s.setCursor&&s.setCursor(r?r.cursor:"default"),o&&r!==o&&this.dispatchToElement(n,"mouseout",t),this.dispatchToElement(a,"mousemove",t),r&&r!==o&&this.dispatchToElement(a,"mouseover",t)},mouseout:function(t){this.dispatchToElement(this._hovered,"mouseout",t);var e,i=t.toElement||t.relatedTarget;do{i=i&&i.parentNode}while(i&&9!==i.nodeType&&!(e=i===this.painterRoot));!e&&this.trigger("globalout",{event:t})},resize:function(t){this._hovered={}},dispatch:function(t,e){var i=this[t];i&&i.call(this,e)},dispose:function(){this.proxy.dispose(),this.storage=this.proxy=this.painter=null},setCursorStyle:function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},dispatchToElement:function(t,e,i){var n=(t=t||{}).target;if(!n||!n.silent){for(var o="on"+e,a=gt(e,t,i);n&&(n[o]&&(a.cancelBubble=n[o].call(n,a)),n.trigger(e,a),n=n.parent,!a.cancelBubble););a.cancelBubble||(this.trigger(e,a),this.painter&&this.painter.eachOtherLayer(function(t){"function"==typeof t[o]&&t[o].call(t,a),t.trigger&&t.trigger(e,a)}))}},findHover:function(t,e,i){for(var n=this.storage.getDisplayList(),o={x:t,y:e},a=n.length-1;a>=0;a--){var r;if(n[a]!==i&&!n[a].ignore&&(r=yt(n[a],t,e))&&(!o.topTarget&&(o.topTarget=n[a]),r!==xw)){o.target=n[a];break}}return o},processGesture:function(t,e){this._gestureMgr||(this._gestureMgr=new vw);var i=this._gestureMgr;"start"===e&&i.clear();var n=i.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&i.clear(),n){var o=n.type;t.gestureEvent=o,this.dispatchToElement({target:n.target},o,n.event)}}},d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){ww.prototype[t]=function(e){var i=this.findHover(e.zrX,e.zrY),n=i.target;if("mousedown"===t)this._downEl=n,this._downPoint=[e.zrX,e.zrY],this._upEl=n;else if("mouseup"===t)this._upEl=n;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||uw(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(i,t,e)}}),h(ww,fw),h(ww,it);var bw="undefined"==typeof Float32Array?Array:Float32Array,Sw=(Object.freeze||Object)({create:xt,identity:_t,copy:wt,mul:bt,translate:St,rotate:Mt,scale:It,invert:Tt,clone:At}),Mw=_t,Iw=5e-5,Tw=function(t){(t=t||{}).position||(this.position=[0,0]),null==t.rotation&&(this.rotation=0),t.scale||(this.scale=[1,1]),this.origin=this.origin||null},Aw=Tw.prototype;Aw.transform=null,Aw.needLocalTransform=function(){return Dt(this.rotation)||Dt(this.position[0])||Dt(this.position[1])||Dt(this.scale[0]-1)||Dt(this.scale[1]-1)};var Dw=[];Aw.updateTransform=function(){var t=this.parent,e=t&&t.transform,i=this.needLocalTransform(),n=this.transform;if(i||e){n=n||xt(),i?this.getLocalTransform(n):Mw(n),e&&(i?bt(n,t.transform,n):wt(n,t.transform)),this.transform=n;var o=this.globalScaleRatio;if(null!=o&&1!==o){this.getGlobalScale(Dw);var a=Dw[0]<0?-1:1,r=Dw[1]<0?-1:1,s=((Dw[0]-a)*o+a)/Dw[0]||0,l=((Dw[1]-r)*o+r)/Dw[1]||0;n[0]*=s,n[1]*=s,n[2]*=l,n[3]*=l}this.invTransform=this.invTransform||xt(),Tt(this.invTransform,n)}else n&&Mw(n)},Aw.getLocalTransform=function(t){return Tw.getLocalTransform(this,t)},Aw.setTransform=function(t){var e=this.transform,i=t.dpr||1;e?t.setTransform(i*e[0],i*e[1],i*e[2],i*e[3],i*e[4],i*e[5]):t.setTransform(i,0,0,i,0,0)},Aw.restoreTransform=function(t){var e=t.dpr||1;t.setTransform(e,0,0,e,0,0)};var Cw=[],Lw=xt();Aw.setLocalTransform=function(t){if(t){var e=t[0]*t[0]+t[1]*t[1],i=t[2]*t[2]+t[3]*t[3],n=this.position,o=this.scale;Dt(e-1)&&(e=Math.sqrt(e)),Dt(i-1)&&(i=Math.sqrt(i)),t[0]<0&&(e=-e),t[3]<0&&(i=-i),n[0]=t[4],n[1]=t[5],o[0]=e,o[1]=i,this.rotation=Math.atan2(-t[1]/i,t[0]/e)}},Aw.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(bt(Cw,t.invTransform,e),e=Cw);var i=this.origin;i&&(i[0]||i[1])&&(Lw[4]=i[0],Lw[5]=i[1],bt(Cw,e,Lw),Cw[4]-=i[0],Cw[5]-=i[1],e=Cw),this.setLocalTransform(e)}},Aw.getGlobalScale=function(t){var e=this.transform;return t=t||[],e?(t[0]=Math.sqrt(e[0]*e[0]+e[1]*e[1]),t[1]=Math.sqrt(e[2]*e[2]+e[3]*e[3]),e[0]<0&&(t[0]=-t[0]),e[3]<0&&(t[1]=-t[1]),t):(t[0]=1,t[1]=1,t)},Aw.transformCoordToLocal=function(t,e){var i=[t,e],n=this.invTransform;return n&&Q(i,i,n),i},Aw.transformCoordToGlobal=function(t,e){var i=[t,e],n=this.transform;return n&&Q(i,i,n),i},Tw.getLocalTransform=function(t,e){Mw(e=e||[]);var i=t.origin,n=t.scale||[1,1],o=t.rotation||0,a=t.position||[0,0];return i&&(e[4]-=i[0],e[5]-=i[1]),It(e,e,n),o&&Mt(e,e,o),i&&(e[4]+=i[0],e[5]+=i[1]),e[4]+=a[0],e[5]+=a[1],e};var kw={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),(t*=2)<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-kw.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*kw.bounceIn(2*t):.5*kw.bounceOut(2*t-1)+.5}};Ct.prototype={constructor:Ct,step:function(t,e){if(this._initialized||(this._startTime=t+this._delay,this._initialized=!0),this._paused)this._pausedTime+=e;else{var i=(t-this._startTime-this._pausedTime)/this._life;if(!(i<0)){i=Math.min(i,1);var n=this.easing,o="string"==typeof n?kw[n]:n,a="function"==typeof o?o(i):i;return this.fire("frame",a),1===i?this.loop?(this.restart(t),"restart"):(this._needsRemove=!0,"destroy"):null}}},restart:function(t){var e=(t-this._startTime-this._pausedTime)%this._life;this._startTime=t-e+this.gap,this._pausedTime=0,this._needsRemove=!1},fire:function(t,e){this[t="on"+t]&&this[t](this._target,e)},pause:function(){this._paused=!0},resume:function(){this._paused=!1}};var Pw=function(){this.head=null,this.tail=null,this._len=0},Nw=Pw.prototype;Nw.insert=function(t){var e=new Ow(t);return this.insertEntry(e),e},Nw.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},Nw.remove=function(t){var e=t.prev,i=t.next;e?e.next=i:this.head=i,i?i.prev=e:this.tail=e,t.next=t.prev=null,this._len--},Nw.len=function(){return this._len},Nw.clear=function(){this.head=this.tail=null,this._len=0};var Ow=function(t){this.value=t,this.next,this.prev},Ew=function(t){this._list=new Pw,this._map={},this._maxSize=t||10,this._lastRemovedEntry=null},Rw=Ew.prototype;Rw.put=function(t,e){var i=this._list,n=this._map,o=null;if(null==n[t]){var a=i.len(),r=this._lastRemovedEntry;if(a>=this._maxSize&&a>0){var s=i.head;i.remove(s),delete n[s.key],o=s.value,this._lastRemovedEntry=s}r?r.value=e:r=new Ow(e),r.key=t,i.insertEntry(r),n[t]=r}return o},Rw.get=function(t){var e=this._map[t],i=this._list;if(null!=e)return e!==i.tail&&(i.remove(e),i.insertEntry(e)),e.value},Rw.clear=function(){this._list.clear(),this._map={}};var zw={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]},Bw=new Ew(20),Vw=null,Gw=Ut,Fw=Xt,Ww=(Object.freeze||Object)({parse:Gt,lift:Ht,toHex:Zt,fastLerp:Ut,fastMapToColor:Gw,lerp:Xt,mapToColor:Fw,modifyHSL:jt,modifyAlpha:Yt,stringify:qt}),Hw=Array.prototype.slice,Zw=function(t,e,i,n){this._tracks={},this._target=t,this._loop=e||!1,this._getter=i||Kt,this._setter=n||$t,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};Zw.prototype={when:function(t,e){var i=this._tracks;for(var n in e)if(e.hasOwnProperty(n)){if(!i[n]){i[n]=[];var o=this._getter(this._target,n);if(null==o)continue;0!==t&&i[n].push({time:0,value:ae(o)})}i[n].push({time:t,value:e[n]})}return this},during:function(t){return this._onframeList.push(t),this},pause:function(){for(var t=0;t=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height},clone:function(){return new de(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},de.create=function(t){return new de(t.x,t.y,t.width,t.height)};var tb=function(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};tb.prototype={constructor:tb,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,i=0;i=0&&(i.splice(n,0,t),this._doAdd(t))}return this},_doAdd:function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__storage,i=this.__zr;e&&e!==t.__storage&&(e.addToStorage(t),t instanceof tb&&t.addChildrenToStorage(e)),i&&i.refresh()},remove:function(t){var e=this.__zr,i=this.__storage,n=this._children,o=l(n,t);return o<0?this:(n.splice(o,1),t.parent=null,i&&(i.delFromStorage(t),t instanceof tb&&t.delChildrenFromStorage(i)),e&&e.refresh(),this)},removeAll:function(){var t,e,i=this._children,n=this.__storage;for(e=0;e=0&&(this.delFromStorage(t),this._roots.splice(o,1),t instanceof tb&&t.delChildrenFromStorage(this))}},addToStorage:function(t){return t&&(t.__storage=this,t.dirty(!1)),this},delFromStorage:function(t){return t&&(t.__storage=null),this},dispose:function(){this._renderList=this._roots=null},displayableSortFunc:we};var ob={shadowBlur:1,shadowOffsetX:1,shadowOffsetY:1,textShadowBlur:1,textShadowOffsetX:1,textShadowOffsetY:1,textBoxShadowBlur:1,textBoxShadowOffsetX:1,textBoxShadowOffsetY:1},ab=function(t,e,i){return ob.hasOwnProperty(e)?i*=t.dpr:i},rb={NONE:0,STYLE_BIND:1,PLAIN_TEXT:2},sb=9,lb=[["shadowBlur",0],["shadowOffsetX",0],["shadowOffsetY",0],["shadowColor","#000"],["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]],ub=function(t){this.extendFrom(t,!1)};ub.prototype={constructor:ub,fill:"#000",stroke:null,opacity:1,fillOpacity:null,strokeOpacity:null,lineDash:null,lineDashOffset:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,lineWidth:1,strokeNoScale:!1,text:null,font:null,textFont:null,fontStyle:null,fontWeight:null,fontSize:null,fontFamily:null,textTag:null,textFill:"#000",textStroke:null,textWidth:null,textHeight:null,textStrokeWidth:0,textLineHeight:null,textPosition:"inside",textRect:null,textOffset:null,textAlign:null,textVerticalAlign:null,textDistance:5,textShadowColor:"transparent",textShadowBlur:0,textShadowOffsetX:0,textShadowOffsetY:0,textBoxShadowColor:"transparent",textBoxShadowBlur:0,textBoxShadowOffsetX:0,textBoxShadowOffsetY:0,transformText:!1,textRotation:0,textOrigin:null,textBackgroundColor:null,textBorderColor:null,textBorderWidth:0,textBorderRadius:0,textPadding:null,rich:null,truncate:null,blend:null,bind:function(t,e,i){var n=this,o=i&&i.style,a=!o||t.__attrCachedBy!==rb.STYLE_BIND;t.__attrCachedBy=rb.STYLE_BIND;for(var r=0;r0},extendFrom:function(t,e){if(t)for(var i in t)!t.hasOwnProperty(i)||!0!==e&&(!1===e?this.hasOwnProperty(i):null==t[i])||(this[i]=t[i])},set:function(t,e){"string"==typeof t?this[t]=e:this.extendFrom(t,!0)},clone:function(){var t=new this.constructor;return t.extendFrom(this,!0),t},getGradient:function(t,e,i){for(var n=("radial"===e.type?Se:be)(t,e,i),o=e.colorStops,a=0;a=0&&i.splice(n,1),t.__hoverMir=null},clearHover:function(t){for(var e=this._hoverElements,i=0;i15)break}s.__drawIndex=m,s.__drawIndex0&&t>n[0]){for(r=0;rt);r++);a=i[n[r]]}if(n.splice(r+1,0,t),i[t]=e,!e.virtual)if(a){var l=a.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else Yw("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var i,n,o=this._zlevelList;for(n=0;n0?.01:0),this._needsManuallyCompositing),a.__builtin__||Yw("ZLevel "+s+" has been used by unkown layer "+a.id),a!==i&&(a.__used=!0,a.__startIndex!==o&&(a.__dirty=!0),a.__startIndex=o,a.incremental?a.__drawIndex=-1:a.__drawIndex=o,e(o),i=a),r.__dirty&&(a.__dirty=!0,a.incremental&&a.__drawIndex<0&&(a.__drawIndex=o))}e(o),this.eachBuiltinLayer(function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)})},clear:function(){return this.eachBuiltinLayer(this._clearLayer),this},_clearLayer:function(t){t.clear()},setBackgroundColor:function(t){this._backgroundColor=t},configLayer:function(t,e){if(e){var i=this._layerConfig;i[t]?n(i[t],e,!0):i[t]=e;for(var o=0;o=0&&this._clips.splice(e,1)},removeAnimator:function(t){for(var e=t.getClips(),i=0;i=0||n&&l(n,r)<0)){var s=e.getShallow(r);null!=s&&(o[t[a][0]]=s)}}return o}},tS=Qb([["lineWidth","width"],["stroke","color"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),eS={getLineStyle:function(t){var e=tS(this,t),i=this.getLineDash(e.lineWidth);return i&&(e.lineDash=i),e},getLineDash:function(t){null==t&&(t=1);var e=this.get("type"),i=Math.max(t,2),n=4*t;return"solid"===e||null==e?null:"dashed"===e?[n,n]:[i,i]}},iS=Qb([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),nS={getAreaStyle:function(t,e){return iS(this,t,e)}},oS=Math.pow,aS=Math.sqrt,rS=1e-8,sS=1e-4,lS=aS(3),uS=1/3,hS=V(),cS=V(),dS=V(),fS=Math.min,pS=Math.max,gS=Math.sin,mS=Math.cos,vS=2*Math.PI,yS=V(),xS=V(),_S=V(),wS=[],bS=[],SS={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},MS=[],IS=[],TS=[],AS=[],DS=Math.min,CS=Math.max,LS=Math.cos,kS=Math.sin,PS=Math.sqrt,NS=Math.abs,OS="undefined"!=typeof Float32Array,ES=function(t){this._saveData=!t,this._saveData&&(this.data=[]),this._ctx=null};ES.prototype={constructor:ES,_xi:0,_yi:0,_x0:0,_y0:0,_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,setScale:function(t,e){this._ux=NS(1/Xw/t)||0,this._uy=NS(1/Xw/e)||0},getContext:function(){return this._ctx},beginPath:function(t){return this._ctx=t,t&&t.beginPath(),t&&(this.dpr=t.dpr),this._saveData&&(this._len=0),this._lineDash&&(this._lineDash=null,this._dashOffset=0),this},moveTo:function(t,e){return this.addData(SS.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},lineTo:function(t,e){var i=NS(t-this._xi)>this._ux||NS(e-this._yi)>this._uy||this._len<5;return this.addData(SS.L,t,e),this._ctx&&i&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),i&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,i,n,o,a){return this.addData(SS.C,t,e,i,n,o,a),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,i,n,o,a):this._ctx.bezierCurveTo(t,e,i,n,o,a)),this._xi=o,this._yi=a,this},quadraticCurveTo:function(t,e,i,n){return this.addData(SS.Q,t,e,i,n),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,i,n):this._ctx.quadraticCurveTo(t,e,i,n)),this._xi=i,this._yi=n,this},arc:function(t,e,i,n,o,a){return this.addData(SS.A,t,e,i,i,n,o-n,0,a?0:1),this._ctx&&this._ctx.arc(t,e,i,n,o,a),this._xi=LS(o)*i+t,this._yi=kS(o)*i+e,this},arcTo:function(t,e,i,n,o){return this._ctx&&this._ctx.arcTo(t,e,i,n,o),this},rect:function(t,e,i,n){return this._ctx&&this._ctx.rect(t,e,i,n),this.addData(SS.R,t,e,i,n),this},closePath:function(){this.addData(SS.Z);var t=this._ctx,e=this._x0,i=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,i),t.closePath()),this._xi=e,this._yi=i,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t,this._dashIdx=0;for(var e=0,i=0;ie.length&&(this._expandData(),e=this.data);for(var i=0;i0&&f<=t||h<0&&f>=t||0===h&&(c>0&&p<=e||c<0&&p>=e);)f+=h*(i=r[n=this._dashIdx]),p+=c*i,this._dashIdx=(n+1)%g,h>0&&fl||c>0&&pu||s[n%2?"moveTo":"lineTo"](h>=0?DS(f,t):CS(f,t),c>=0?DS(p,e):CS(p,e));h=f-t,c=p-e,this._dashOffset=-PS(h*h+c*c)},_dashedBezierTo:function(t,e,i,n,o,a){var r,s,l,u,h,c=this._dashSum,d=this._dashOffset,f=this._lineDash,p=this._ctx,g=this._xi,m=this._yi,v=tn,y=0,x=this._dashIdx,_=f.length,w=0;for(d<0&&(d=c+d),d%=c,r=0;r<1;r+=.1)s=v(g,t,i,o,r+.1)-v(g,t,i,o,r),l=v(m,e,n,a,r+.1)-v(m,e,n,a,r),y+=PS(s*s+l*l);for(;x<_&&!((w+=f[x])>d);x++);for(r=(w-d)/y;r<=1;)u=v(g,t,i,o,r),h=v(m,e,n,a,r),x%2?p.moveTo(u,h):p.lineTo(u,h),r+=f[x]/y,x=(x+1)%_;x%2!=0&&p.lineTo(o,a),s=o-u,l=a-h,this._dashOffset=-PS(s*s+l*l)},_dashedQuadraticTo:function(t,e,i,n){var o=i,a=n;i=(i+2*t)/3,n=(n+2*e)/3,t=(this._xi+2*t)/3,e=(this._yi+2*e)/3,this._dashedBezierTo(t,e,i,n,o,a)},toStatic:function(){var t=this.data;t instanceof Array&&(t.length=this._len,OS&&(this.data=new Float32Array(t)))},getBoundingRect:function(){MS[0]=MS[1]=TS[0]=TS[1]=Number.MAX_VALUE,IS[0]=IS[1]=AS[0]=AS[1]=-Number.MAX_VALUE;for(var t=this.data,e=0,i=0,n=0,o=0,a=0;al||NS(r-o)>u||c===h-1)&&(t.lineTo(a,r),n=a,o=r);break;case SS.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=g>m?g:m,b=g>m?1:g/m,S=g>m?m/g:1,M=v+y;Math.abs(g-m)>.001?(t.translate(f,p),t.rotate(x),t.scale(b,S),t.arc(0,0,w,v,M,1-_),t.scale(1/b,1/S),t.rotate(-x),t.translate(-f,-p)):t.arc(f,p,w,v,M,1-_),1===c&&(e=LS(v)*g+f,i=kS(v)*m+p),n=LS(M)*g+f,o=kS(M)*m+p;break;case SS.R:e=n=s[c],i=o=s[c+1],t.rect(s[c++],s[c++],s[c++],s[c++]);break;case SS.Z:t.closePath(),n=e,o=i}}}},ES.CMD=SS;var RS=2*Math.PI,zS=2*Math.PI,BS=ES.CMD,VS=2*Math.PI,GS=1e-4,FS=[-1,-1,-1],WS=[-1,-1],HS=fb.prototype.getCanvasPattern,ZS=Math.abs,US=new ES(!0);Pn.prototype={constructor:Pn,type:"path",__dirtyPath:!0,strokeContainThreshold:5,subPixelOptimize:!1,brush:function(t,e){var i=this.style,n=this.path||US,o=i.hasStroke(),a=i.hasFill(),r=i.fill,s=i.stroke,l=a&&!!r.colorStops,u=o&&!!s.colorStops,h=a&&!!r.image,c=o&&!!s.image;if(i.bind(t,this,e),this.setTransform(t),this.__dirty){var d;l&&(d=d||this.getBoundingRect(),this._fillGradient=i.getGradient(t,r,d)),u&&(d=d||this.getBoundingRect(),this._strokeGradient=i.getGradient(t,s,d))}l?t.fillStyle=this._fillGradient:h&&(t.fillStyle=HS.call(r,t)),u?t.strokeStyle=this._strokeGradient:c&&(t.strokeStyle=HS.call(s,t));var f=i.lineDash,p=i.lineDashOffset,g=!!t.setLineDash,m=this.getGlobalScale();if(n.setScale(m[0],m[1]),this.__dirtyPath||f&&!g&&o?(n.beginPath(t),f&&!g&&(n.setLineDash(f),n.setLineDashOffset(p)),this.buildPath(n,this.shape,!1),this.path&&(this.__dirtyPath=!1)):(t.beginPath(),this.path.rebuildPath(t)),a)if(null!=i.fillOpacity){v=t.globalAlpha;t.globalAlpha=i.fillOpacity*i.opacity,n.fill(t),t.globalAlpha=v}else n.fill(t);if(f&&g&&(t.setLineDash(f),t.lineDashOffset=p),o)if(null!=i.strokeOpacity){var v=t.globalAlpha;t.globalAlpha=i.strokeOpacity*i.opacity,n.stroke(t),t.globalAlpha=v}else n.stroke(t);f&&g&&t.setLineDash([]),null!=i.text&&(this.restoreTransform(t),this.drawRectText(t,this.getBoundingRect()))},buildPath:function(t,e,i){},createPathProxy:function(){this.path=new ES},getBoundingRect:function(){var t=this._rect,e=this.style,i=!t;if(i){var n=this.path;n||(n=this.path=new ES),this.__dirtyPath&&(n.beginPath(),this.buildPath(n,this.shape,!1)),t=n.getBoundingRect()}if(this._rect=t,e.hasStroke()){var o=this._rectWithStroke||(this._rectWithStroke=t.clone());if(this.__dirty||i){o.copy(t);var a=e.lineWidth,r=e.strokeNoScale?this.getLineScale():1;e.hasFill()||(a=Math.max(a,this.strokeContainThreshold||4)),r>1e-10&&(o.width+=a/r,o.height+=a/r,o.x-=a/r/2,o.y-=a/r/2)}return o}return t},contain:function(t,e){var i=this.transformCoordToLocal(t,e),n=this.getBoundingRect(),o=this.style;if(t=i[0],e=i[1],n.contain(t,e)){var a=this.path.data;if(o.hasStroke()){var r=o.lineWidth,s=o.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(o.hasFill()||(r=Math.max(r,this.strokeContainThreshold)),kn(a,r/s,t,e)))return!0}if(o.hasFill())return Ln(a,t,e)}return!1},dirty:function(t){null==t&&(t=!0),t&&(this.__dirtyPath=t,this._rect=null),this.__dirty=this.__dirtyText=!0,this.__zr&&this.__zr.refresh(),this.__clipTarget&&this.__clipTarget.dirty()},animateShape:function(t){return this.animate("shape",t)},attrKV:function(t,e){"shape"===t?(this.setShape(e),this.__dirtyPath=!0,this._rect=null):di.prototype.attrKV.call(this,t,e)},setShape:function(t,e){var i=this.shape;if(i){if(w(t))for(var n in t)t.hasOwnProperty(n)&&(i[n]=t[n]);else i[t]=e;this.dirty(!0)}return this},getLineScale:function(){var t=this.transform;return t&&ZS(t[0]-1)>1e-10&&ZS(t[3]-1)>1e-10?Math.sqrt(ZS(t[0]*t[3]-t[2]*t[1])):1}},Pn.extend=function(t){var e=function(e){Pn.call(this,e),t.style&&this.style.extendFrom(t.style,!1);var i=t.shape;if(i){this.shape=this.shape||{};var n=this.shape;for(var o in i)!n.hasOwnProperty(o)&&i.hasOwnProperty(o)&&(n[o]=i[o])}t.init&&t.init.call(this,e)};u(e,Pn);for(var i in t)"style"!==i&&"shape"!==i&&(e.prototype[i]=t[i]);return e},u(Pn,di);var XS=ES.CMD,jS=[[],[],[]],YS=Math.sqrt,qS=Math.atan2,KS=function(t,e){var i,n,o,a,r,s,l=t.data,u=XS.M,h=XS.C,c=XS.L,d=XS.R,f=XS.A,p=XS.Q;for(o=0,a=0;o=11?function(){var e,i=this.__clipPaths,n=this.style;if(i)for(var o=0;oi-2?i-1:c+1],u=t[c>i-3?i-1:c+2]);var p=d*d,g=d*p;n.push([Bn(s[0],f[0],l[0],u[0],d,p,g),Bn(s[1],f[1],l[1],u[1],d,p,g)])}return n},fM=function(t,e,i,n){var o,a,r,s,l=[],u=[],h=[],c=[];if(n){r=[1/0,1/0],s=[-1/0,-1/0];for(var d=0,f=t.length;d=i&&a>=o)return{x:i,y:o,width:n-i,height:a-o}},createIcon:Po,Group:tb,Image:fi,Text:rM,Circle:sM,Sector:hM,Ring:cM,Polygon:pM,Polyline:gM,Rect:yM,Line:_M,BezierCurve:bM,Arc:SM,IncrementalDisplayable:Zn,CompoundPath:MM,LinearGradient:TM,RadialGradient:AM,BoundingRect:de}),BM=["textStyle","color"],VM={getTextColor:function(t){var e=this.ecModel;return this.getShallow("color")||(!t&&e?e.get(BM):null)},getFont:function(){return So({fontStyle:this.getShallow("fontStyle"),fontWeight:this.getShallow("fontWeight"),fontSize:this.getShallow("fontSize"),fontFamily:this.getShallow("fontFamily")},this.ecModel)},getTextRect:function(t){return ke(t,this.getFont(),this.getShallow("align"),this.getShallow("verticalAlign")||this.getShallow("baseline"),this.getShallow("padding"),this.getShallow("lineHeight"),this.getShallow("rich"),this.getShallow("truncateText"))}},GM=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"],["textPosition"],["textAlign"]]),FM={getItemStyle:function(t,e){var i=GM(this,t,e),n=this.getBorderLineDash();return n&&(i.lineDash=n),i},getBorderLineDash:function(){var t=this.get("borderType");return"solid"===t||null==t?null:"dashed"===t?[5,5]:[1,1]}},WM=h,HM=Bi();No.prototype={constructor:No,init:null,mergeOption:function(t){n(this.option,t,!0)},get:function(t,e){return null==t?this.option:Oo(this.option,this.parsePath(t),!e&&Eo(this,t))},getShallow:function(t,e){var i=this.option,n=null==i?i:i[t],o=!e&&Eo(this,t);return null==n&&o&&(n=o.getShallow(t)),n},getModel:function(t,e){var i,n=null==t?this.option:Oo(this.option,t=this.parsePath(t));return e=e||(i=Eo(this,t))&&i.getModel(t),new No(n,e,this.ecModel)},isEmpty:function(){return null==this.option},restoreData:function(){},clone:function(){return new(0,this.constructor)(i(this.option))},setReadOnly:function(t){},parsePath:function(t){return"string"==typeof t&&(t=t.split(".")),t},customizeGetParent:function(t){HM(this).getParent=t},isAnimationEnabled:function(){if(!U_.node){if(null!=this.option.animation)return!!this.option.animation;if(this.parentModel)return this.parentModel.isAnimationEnabled()}}},ji(No),Yi(No),WM(No,eS),WM(No,nS),WM(No,VM),WM(No,FM);var ZM=0,UM=1e-4,XM=9007199254740991,jM=/^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/,YM=(Object.freeze||Object)({linearMap:Bo,parsePercent:Vo,round:Go,asc:Fo,getPrecision:Wo,getPrecisionSafe:Ho,getPixelPrecision:Zo,getPercentWithPrecision:Uo,MAX_SAFE_INTEGER:XM,remRadian:Xo,isRadianAroundZero:jo,parseDate:Yo,quantity:qo,nice:$o,quantile:function(t,e){var i=(t.length-1)*e+1,n=Math.floor(i),o=+t[n-1],a=i-n;return a?o+a*(t[n]-o):o},reformIntervals:Jo,isNumeric:Qo}),qM=L,KM=/([&<>"'])/g,$M={"&":"&","<":"<",">":">",'"':""","'":"'"},JM=["a","b","c","d","e","f","g"],QM=function(t,e){return"{"+t+(null==e?"":e)+"}"},tI=ze,eI=(Object.freeze||Object)({addCommas:ta,toCamelCase:ea,normalizeCssArray:qM,encodeHTML:ia,formatTpl:na,formatTplSimple:oa,getTooltipMarker:aa,formatTime:sa,capitalFirst:la,truncateText:tI,getTextBoundingRect:function(t){return ke(t.text,t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich,t.truncate)},getTextRect:function(t,e,i,n,o,a,r,s){return ke(t,e,i,n,o,s,a,r)}}),iI=d,nI=["left","right","top","bottom","width","height"],oI=[["width","left","right"],["height","top","bottom"]],aI=ua,rI=(v(ua,"vertical"),v(ua,"horizontal"),{getBoxLayoutParams:function(){return{left:this.get("left"),top:this.get("top"),right:this.get("right"),bottom:this.get("bottom"),width:this.get("width"),height:this.get("height")}}}),sI=Bi(),lI=No.extend({type:"component",id:"",name:"",mainType:"",subType:"",componentIndex:0,defaultOption:null,ecModel:null,dependentModels:[],uid:null,layoutMode:null,$constructor:function(t,e,i,n){No.call(this,t,e,i,n),this.uid=Ro("ec_cpt_model")},init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i)},mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,o=i?ga(t):{};n(t,e.getTheme().get(this.mainType)),n(t,this.getDefaultOption()),i&&pa(t,o,i)},mergeOption:function(t,e){n(this.option,t,!0);var i=this.layoutMode;i&&pa(this.option,t,i)},optionUpdated:function(t,e){},getDefaultOption:function(){var t=sI(this);if(!t.defaultOption){for(var e=[],i=this.constructor;i;){var o=i.prototype.defaultOption;o&&e.push(o),i=i.superClass}for(var a={},r=e.length-1;r>=0;r--)a=n(a,e[r],!0);t.defaultOption=a}return t.defaultOption},getReferringComponents:function(t){return this.ecModel.queryComponents({mainType:t,index:this.get(t+"Index",!0),id:this.get(t+"Id",!0)})}});$i(lI,{registerWhenExtend:!0}),function(t){var e={};t.registerSubTypeDefaulter=function(t,i){t=Ui(t),e[t.main]=i},t.determineSubType=function(i,n){var o=n.type;if(!o){var a=Ui(i).main;t.hasSubTypes(i)&&e[a]&&(o=e[a](n))}return o}}(lI),function(t,e){function i(t){var i={},a=[];return d(t,function(r){var s=n(i,r),u=o(s.originalDeps=e(r),t);s.entryCount=u.length,0===s.entryCount&&a.push(r),d(u,function(t){l(s.predecessor,t)<0&&s.predecessor.push(t);var e=n(i,t);l(e.successor,t)<0&&e.successor.push(r)})}),{graph:i,noEntryList:a}}function n(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}function o(t,e){var i=[];return d(t,function(t){l(e,t)>=0&&i.push(t)}),i}t.topologicalTravel=function(t,e,n,o){function a(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}if(t.length){var r=i(e),s=r.graph,l=r.noEntryList,u={};for(d(t,function(t){u[t]=!0});l.length;){var h=l.pop(),c=s[h],f=!!u[h];f&&(n.call(o,h,c.originalDeps.slice()),delete u[h]),d(c.successor,f?function(t){u[t]=!0,a(t)}:a)}d(u,function(){throw new Error("Circle dependency may exists")})}}}(lI,function(t){var e=[];return d(lI.getClassesByMainType(t),function(t){e=e.concat(t.prototype.dependencies||[])}),e=f(e,function(t){return Ui(t).main}),"dataset"!==t&&l(e,"dataset")<=0&&e.unshift("dataset"),e}),h(lI,rI);var uI="";"undefined"!=typeof navigator&&(uI=navigator.platform||"");var hI={color:["#c23531","#2f4554","#61a0a8","#d48265","#91c7ae","#749f83","#ca8622","#bda29a","#6e7074","#546570","#c4ccd3"],gradientColor:["#f6efa6","#d88273","#bf444c"],textStyle:{fontFamily:uI.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,animation:"auto",animationDuration:1e3,animationDurationUpdate:300,animationEasing:"exponentialOut",animationEasingUpdate:"cubicOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},cI=Bi(),dI={clearColorPalette:function(){cI(this).colorIdx=0,cI(this).colorNameMap={}},getColorFromPalette:function(t,e,i){var n=cI(e=e||this),o=n.colorIdx||0,a=n.colorNameMap=n.colorNameMap||{};if(a.hasOwnProperty(t))return a[t];var r=Di(this.get("color",!0)),s=this.get("colorLayer",!0),l=null!=i&&s?va(s,i):r;if((l=l||r)&&l.length){var u=l[o];return t&&(a[t]=u),n.colorIdx=(o+1)%l.length,u}}},fI={cartesian2d:function(t,e,i,n){var o=t.getReferringComponents("xAxis")[0],a=t.getReferringComponents("yAxis")[0];e.coordSysDims=["x","y"],i.set("x",o),i.set("y",a),xa(o)&&(n.set("x",o),e.firstCategoryDimIndex=0),xa(a)&&(n.set("y",a),e.firstCategoryDimIndex=1)},singleAxis:function(t,e,i,n){var o=t.getReferringComponents("singleAxis")[0];e.coordSysDims=["single"],i.set("single",o),xa(o)&&(n.set("single",o),e.firstCategoryDimIndex=0)},polar:function(t,e,i,n){var o=t.getReferringComponents("polar")[0],a=o.findAxisModel("radiusAxis"),r=o.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],i.set("radius",a),i.set("angle",r),xa(a)&&(n.set("radius",a),e.firstCategoryDimIndex=0),xa(r)&&(n.set("angle",r),e.firstCategoryDimIndex=1)},geo:function(t,e,i,n){e.coordSysDims=["lng","lat"]},parallel:function(t,e,i,n){var o=t.ecModel,a=o.getComponent("parallel",t.get("parallelIndex")),r=e.coordSysDims=a.dimensions.slice();d(a.parallelAxisIndex,function(t,a){var s=o.getComponent("parallelAxis",t),l=r[a];i.set(l,s),xa(s)&&null==e.firstCategoryDimIndex&&(n.set(l,s),e.firstCategoryDimIndex=a)})}},pI="original",gI="arrayRows",mI="objectRows",vI="keyedColumns",yI="unknown",xI="typedArray",_I="column",wI="row";_a.seriesDataToSource=function(t){return new _a({data:t,sourceFormat:S(t)?xI:pI,fromDataset:!1})},Yi(_a);var bI=Bi(),SI="\0_ec_inner",MI=No.extend({init:function(t,e,i,n){i=i||{},this.option=null,this._theme=new No(i),this._optionManager=n},setOption:function(t,e){k(!(SI in t),"please use chart.getOption()"),this._optionManager.setOption(t,e),this.resetOption(null)},resetOption:function(t){var e=!1,i=this._optionManager;if(!t||"recreate"===t){var n=i.mountOption("recreate"===t);this.option&&"recreate"!==t?(this.restoreData(),this.mergeOption(n)):Ea.call(this,n),e=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var o=i.getTimelineOption(this);o&&(this.mergeOption(o),e=!0)}if(!t||"recreate"===t||"media"===t){var a=i.getMediaOption(this,this._api);a.length&&d(a,function(t){this.mergeOption(t,e=!0)},this)}return e},mergeOption:function(t){var e=this.option,o=this._componentsMap,r=[];Sa(this),d(t,function(t,o){null!=t&&(lI.hasClass(o)?o&&r.push(o):e[o]=null==e[o]?i(t):n(e[o],t,!0))}),lI.topologicalTravel(r,lI.getAllClassMainTypes(),function(i,n){var r=Di(t[i]),s=Pi(o.get(i),r);Ni(s),d(s,function(t,e){var n=t.option;w(n)&&(t.keyInfo.mainType=i,t.keyInfo.subType=za(i,n,t.exist))});var l=Ra(o,n);e[i]=[],o.set(i,[]),d(s,function(t,n){var r=t.exist,s=t.option;if(k(w(s)||r,"Empty component definition"),s){var u=lI.getClass(i,t.keyInfo.subType,!0);if(r&&r instanceof u)r.name=t.keyInfo.name,r.mergeOption(s,this),r.optionUpdated(s,!1);else{var h=a({dependentModels:l,componentIndex:n},t.keyInfo);a(r=new u(s,this,this,h),h),r.init(s,this,this,h),r.optionUpdated(null,!0)}}else r.mergeOption({},this),r.optionUpdated({},!1);o.get(i)[n]=r,e[i][n]=r.option},this),"series"===i&&Ba(this,o.get("series"))},this),this._seriesIndicesMap=R(this._seriesIndices=this._seriesIndices||[])},getOption:function(){var t=i(this.option);return d(t,function(e,i){if(lI.hasClass(i)){for(var n=(e=Di(e)).length-1;n>=0;n--)Ei(e[n])&&e.splice(n,1);t[i]=e}}),delete t[SI],t},getTheme:function(){return this._theme},getComponent:function(t,e){var i=this._componentsMap.get(t);if(i)return i[e||0]},queryComponents:function(t){var e=t.mainType;if(!e)return[];var i=t.index,n=t.id,o=t.name,a=this._componentsMap.get(e);if(!a||!a.length)return[];var r;if(null!=i)y(i)||(i=[i]),r=g(f(i,function(t){return a[t]}),function(t){return!!t});else if(null!=n){var s=y(n);r=g(a,function(t){return s&&l(n,t.id)>=0||!s&&t.id===n})}else if(null!=o){var u=y(o);r=g(a,function(t){return u&&l(o,t.name)>=0||!u&&t.name===o})}else r=a.slice();return Va(r,t)},findComponents:function(t){var e=t.query,i=t.mainType,n=function(t){var e=i+"Index",n=i+"Id",o=i+"Name";return!t||null==t[e]&&null==t[n]&&null==t[o]?null:{mainType:i,index:t[e],id:t[n],name:t[o]}}(e);return function(e){return t.filter?g(e,t.filter):e}(Va(n?this.queryComponents(n):this._componentsMap.get(i),t))},eachComponent:function(t,e,i){var n=this._componentsMap;"function"==typeof t?(i=e,e=t,n.each(function(t,n){d(t,function(t,o){e.call(i,n,t,o)})})):_(t)?d(n.get(t),e,i):w(t)&&d(this.findComponents(t),e,i)},getSeriesByName:function(t){return g(this._componentsMap.get("series"),function(e){return e.name===t})},getSeriesByIndex:function(t){return this._componentsMap.get("series")[t]},getSeriesByType:function(t){return g(this._componentsMap.get("series"),function(e){return e.subType===t})},getSeries:function(){return this._componentsMap.get("series").slice()},getSeriesCount:function(){return this._componentsMap.get("series").length},eachSeries:function(t,e){d(this._seriesIndices,function(i){var n=this._componentsMap.get("series")[i];t.call(e,n,i)},this)},eachRawSeries:function(t,e){d(this._componentsMap.get("series"),t,e)},eachSeriesByType:function(t,e,i){d(this._seriesIndices,function(n){var o=this._componentsMap.get("series")[n];o.subType===t&&e.call(i,o,n)},this)},eachRawSeriesByType:function(t,e,i){return d(this.getSeriesByType(t),e,i)},isSeriesFiltered:function(t){return null==this._seriesIndicesMap.get(t.componentIndex)},getCurrentSeriesIndices:function(){return(this._seriesIndices||[]).slice()},filterSeries:function(t,e){Ba(this,g(this._componentsMap.get("series"),t,e))},restoreData:function(t){var e=this._componentsMap;Ba(this,e.get("series"));var i=[];e.each(function(t,e){i.push(e)}),lI.topologicalTravel(i,lI.getAllClassMainTypes(),function(i,n){d(e.get(i),function(e){("series"!==i||!Na(e,t))&&e.restoreData()})})}});h(MI,dI);var II=["getDom","getZr","getWidth","getHeight","getDevicePixelRatio","dispatchAction","isDisposed","on","off","getDataURL","getConnectedDataURL","getModel","getOption","getViewOfComponentModel","getViewOfSeriesModel"],TI={};Fa.prototype={constructor:Fa,create:function(t,e){var i=[];d(TI,function(n,o){var a=n.create(t,e);i=i.concat(a||[])}),this._coordinateSystems=i},update:function(t,e){d(this._coordinateSystems,function(i){i.update&&i.update(t,e)})},getCoordinateSystems:function(){return this._coordinateSystems.slice()}},Fa.register=function(t,e){TI[t]=e},Fa.get=function(t){return TI[t]};var AI=d,DI=i,CI=f,LI=n,kI=/^(min|max)?(.+)$/;Wa.prototype={constructor:Wa,setOption:function(t,e){t&&d(Di(t.series),function(t){t&&t.data&&S(t.data)&&N(t.data)}),t=DI(t,!0);var i=this._optionBackup,n=Ha.call(this,t,e,!i);this._newBaseOption=n.baseOption,i?(ja(i.baseOption,n.baseOption),n.timelineOptions.length&&(i.timelineOptions=n.timelineOptions),n.mediaList.length&&(i.mediaList=n.mediaList),n.mediaDefault&&(i.mediaDefault=n.mediaDefault)):this._optionBackup=n},mountOption:function(t){var e=this._optionBackup;return this._timelineOptions=CI(e.timelineOptions,DI),this._mediaList=CI(e.mediaList,DI),this._mediaDefault=DI(e.mediaDefault),this._currentMediaIndices=[],DI(t?e.baseOption:this._newBaseOption)},getTimelineOption:function(t){var e,i=this._timelineOptions;if(i.length){var n=t.getComponent("timeline");n&&(e=DI(i[n.getCurrentIndex()],!0))}return e},getMediaOption:function(t){var e=this._api.getWidth(),i=this._api.getHeight(),n=this._mediaList,o=this._mediaDefault,a=[],r=[];if(!n.length&&!o)return r;for(var s=0,l=n.length;s=1)&&(t=1),t}var i=this._upstream,n=t&&t.skip;if(this._dirty&&i){var o=this.context;o.data=o.outputData=i.context.outputData}this.__pipeline&&(this.__pipeline.currentTask=this);var a;this._plan&&!n&&(a=this._plan(this.context));var r=e(this._modBy),s=this._modDataCount||0,l=e(t&&t.modBy),u=t&&t.modDataCount||0;r===l&&s===u||(a="reset");var h;(this._dirty||"reset"===a)&&(this._dirty=!1,h=yr(this,n)),this._modBy=l,this._modDataCount=u;var c=t&&t.step;if(this._dueEnd=i?i._outputDueEnd:this._count?this._count(this.context):1/0,this._progress){var d=this._dueIndex,f=Math.min(null!=c?this._dueIndex+c:1/0,this._dueEnd);if(!n&&(h||d=i?null:t1&&a>0?e:t}};return s}();UI.dirty=function(){this._dirty=!0,this._onDirty&&this._onDirty(this.context)},UI.unfinished=function(){return this._progress&&this._dueIndex":"\n",s="richText"===n,l={},u=0,h=this.getData(),c=h.mapDimension("defaultedTooltip",!0),f=c.length,g=this.getRawValue(t),m=y(g),v=h.getItemVisual(t,"color");w(v)&&v.colorStops&&(v=(v.colorStops[0]||{}).color),v=v||"transparent";var x=(f>1||m&&!f?function(i){function o(t,i){var o=h.getDimensionInfo(i);if(o&&!1!==o.otherDims.tooltip){var c=o.type,d="sub"+a.seriesIndex+"at"+u,p=aa({color:v,type:"subItem",renderMode:n,markerId:d}),g="string"==typeof p?p:p.content,m=(r?g+ia(o.displayName||"-")+": ":"")+ia("ordinal"===c?t+"":"time"===c?e?"":sa("yyyy/MM/dd hh:mm:ss",t):ta(t));m&&f.push(m),s&&(l[d]=v,++u)}}var r=p(i,function(t,e,i){var n=h.getDimensionInfo(i);return t|=n&&!1!==n.tooltip&&null!=n.displayName},0),f=[];c.length?d(c,function(e){o(fr(h,t,e),e)}):d(i,o);var g=r?s?"\n":"
":"",m=g+f.join(g||", ");return{renderMode:n,content:m,style:l}}(g):o(f?fr(h,t,c[0]):m?g[0]:g)).content,_=a.seriesIndex+"at"+u,b=aa({color:v,type:"item",renderMode:n,markerId:_});l[_]=v,++u;var S=h.getName(t),M=this.name;Oi(this)||(M=""),M=M?ia(M)+(e?": ":r):"";var I="string"==typeof b?b:b.content;return{html:e?I+M+x:M+I+(S?ia(S)+": "+x:x),markers:l}},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,i){var n=this.ecModel,o=dI.getColorFromPalette.call(this,t,e,i);return o||(o=n.getColorFromPalette(t,e,i)),o},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});h(YI,ZI),h(YI,dI);var qI=function(){this.group=new tb,this.uid=Ro("viewComponent")};qI.prototype={constructor:qI,init:function(t,e){},render:function(t,e,i,n){},dispose:function(){},filterForExposedEvent:null};var KI=qI.prototype;KI.updateView=KI.updateLayout=KI.updateVisual=function(t,e,i,n){},ji(qI),$i(qI,{registerWhenExtend:!0});var $I=function(){var t=Bi();return function(e){var i=t(e),n=e.pipelineContext,o=i.large,a=i.progressiveRender,r=i.large=n.large,s=i.progressiveRender=n.progressiveRender;return!!(o^r||a^s)&&"reset"}},JI=Bi(),QI=$I();Ar.prototype={type:"chart",init:function(t,e){},render:function(t,e,i,n){},highlight:function(t,e,i,n){Cr(t.getData(),n,"emphasis")},downplay:function(t,e,i,n){Cr(t.getData(),n,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null,filterForExposedEvent:null};var tT=Ar.prototype;tT.updateView=tT.updateLayout=tT.updateVisual=function(t,e,i,n){this.render(t,e,i,n)},ji(Ar),$i(Ar,{registerWhenExtend:!0}),Ar.markUpdateMethod=function(t,e){JI(t).updateMethod=e};var eT={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},iT="\0__throttleOriginMethod",nT="\0__throttleRate",oT="\0__throttleType",aT={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var i=t.getData(),n=(t.visualColorAccessPath||"itemStyle.color").split("."),o=t.get(n)||t.getColorFromPalette(t.name,null,e.getSeriesCount());if(i.setVisual("color",o),!e.isSeriesFiltered(t)){"function"!=typeof o||o instanceof IM||i.each(function(e){i.setItemVisual(e,"color",o(t.getDataParams(e)))});return{dataEach:i.hasItemOption?function(t,e){var i=t.getItemModel(e).get(n,!0);null!=i&&t.setItemVisual(e,"color",i)}:null}}}},rT={toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}},sT=function(t,e){function i(t,e){if("string"!=typeof t)return t;var i=t;return d(e,function(t,e){i=i.replace(new RegExp("\\{\\s*"+e+"\\s*\\}","g"),t)}),i}function n(t){var e=a.get(t);if(null==e){for(var i=t.split("."),n=rT.aria,o=0;o1?"series.multiple.prefix":"series.single.prefix"),{seriesCount:r}),e.eachSeries(function(t,e){if(e1?"multiple":"single")+".";a=i(a=n(s?u+"withName":u+"withoutName"),{seriesId:t.seriesIndex,seriesName:t.get("name"),seriesType:o(t.subType)});var c=t.getData();window.data=c,c.count()>l?a+=i(n("data.partialData"),{displayCnt:l}):a+=n("data.allData");for(var d=[],p=0;pi.blockIndex?i.step:null,a=n&&n.modDataCount;return{step:o,modBy:null!=a?Math.ceil(a/o):null,modDataCount:a}}},uT.getPipeline=function(t){return this._pipelineMap.get(t)},uT.updateStreamModes=function(t,e){var i=this._pipelineMap.get(t.uid),n=t.getData().count(),o=i.progressiveEnabled&&e.incrementalPrepareRender&&n>=i.threshold,a=t.get("large")&&n>=t.get("largeThreshold"),r="mod"===t.get("progressiveChunkMode")?n:null;t.pipelineContext=i.context={progressiveRender:o,modDataCount:r,large:a}},uT.restorePipelines=function(t){var e=this,i=e._pipelineMap=R();t.eachSeries(function(t){var n=t.getProgressive(),o=t.uid;i.set(o,{id:o,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:n&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(n||700),count:0}),jr(e,t,t.dataTask)})},uT.prepareStageTasks=function(){var t=this._stageTaskMap,e=this.ecInstance.getModel(),i=this.api;d(this._allHandlers,function(n){var o=t.get(n.uid)||t.set(n.uid,[]);n.reset&&zr(this,n,o,e,i),n.overallReset&&Br(this,n,o,e,i)},this)},uT.prepareView=function(t,e,i,n){var o=t.renderTask,a=o.context;a.model=e,a.ecModel=i,a.api=n,o.__block=!t.incrementalPrepareRender,jr(this,e,o)},uT.performDataProcessorTasks=function(t,e){Rr(this,this._dataProcessorHandlers,t,e,{block:!0})},uT.performVisualTasks=function(t,e,i){Rr(this,this._visualHandlers,t,e,i)},uT.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},uT.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var hT=uT.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},cT=Ur(0);Er.wrapStageHandler=function(t,e){return x(t)&&(t={overallReset:t,seriesType:Yr(t)}),t.uid=Ro("stageHandler"),e&&(t.visualType=e),t};var dT,fT={},pT={};qr(fT,MI),qr(pT,Ga),fT.eachSeriesByType=fT.eachRawSeriesByType=function(t){dT=t},fT.eachComponent=function(t){"series"===t.mainType&&t.subType&&(dT=t.subType)};var gT=["#37A2DA","#32C5E9","#67E0E3","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#E062AE","#E690D1","#e7bcf3","#9d96f5","#8378EA","#96BFFF"],mT={color:gT,colorLayer:[["#37A2DA","#ffd85c","#fd7b5f"],["#37A2DA","#67E0E3","#FFDB5C","#ff9f7f","#E062AE","#9d96f5"],["#37A2DA","#32C5E9","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#e7bcf3","#8378EA","#96BFFF"],gT]},vT=["#dd6b66","#759aa0","#e69d87","#8dc1a9","#ea7e53","#eedd78","#73a373","#73b9bc","#7289ab","#91ca8c","#f49f42"],yT={color:vT,backgroundColor:"#333",tooltip:{axisPointer:{lineStyle:{color:"#eee"},crossStyle:{color:"#eee"}}},legend:{textStyle:{color:"#eee"}},textStyle:{color:"#eee"},title:{textStyle:{color:"#eee"}},toolbox:{iconStyle:{normal:{borderColor:"#eee"}}},dataZoom:{textStyle:{color:"#eee"}},visualMap:{textStyle:{color:"#eee"}},timeline:{lineStyle:{color:"#eee"},itemStyle:{normal:{color:vT[1]}},label:{normal:{textStyle:{color:"#eee"}}},controlStyle:{normal:{color:"#eee",borderColor:"#eee"}}},timeAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},logAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},valueAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},categoryAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},line:{symbol:"circle"},graph:{color:vT},gauge:{title:{textStyle:{color:"#eee"}}},candlestick:{itemStyle:{normal:{color:"#FD1050",color0:"#0CF49B",borderColor:"#FD1050",borderColor0:"#0CF49B"}}}};yT.categoryAxis.splitLine.show=!1,lI.extend({type:"dataset",defaultOption:{seriesLayoutBy:_I,sourceHeader:null,dimensions:null,source:null},optionUpdated:function(){wa(this)}}),qI.extend({type:"dataset"});var xT=Pn.extend({type:"ellipse",shape:{cx:0,cy:0,rx:0,ry:0},buildPath:function(t,e){var i=.5522848,n=e.cx,o=e.cy,a=e.rx,r=e.ry,s=a*i,l=r*i;t.moveTo(n-a,o),t.bezierCurveTo(n-a,o-l,n-s,o-r,n,o-r),t.bezierCurveTo(n+s,o-r,n+a,o-l,n+a,o),t.bezierCurveTo(n+a,o+l,n+s,o+r,n,o+r),t.bezierCurveTo(n-s,o+r,n-a,o+l,n-a,o),t.closePath()}}),_T=/[\s,]+/;$r.prototype.parse=function(t,e){e=e||{};var i=Kr(t);if(!i)throw new Error("Illegal svg");var n=new tb;this._root=n;var o=i.getAttribute("viewBox")||"",a=parseFloat(i.getAttribute("width")||e.width),r=parseFloat(i.getAttribute("height")||e.height);isNaN(a)&&(a=null),isNaN(r)&&(r=null),es(i,n,null,!0);for(var s=i.firstChild;s;)this._parseNode(s,n),s=s.nextSibling;var l,u;if(o){var h=P(o).split(_T);h.length>=4&&(l={x:parseFloat(h[0]||0),y:parseFloat(h[1]||0),width:parseFloat(h[2]),height:parseFloat(h[3])})}if(l&&null!=a&&null!=r&&(u=as(l,a,r),!e.ignoreViewBox)){var c=n;(n=new tb).add(c),c.scale=u.scale.slice(),c.position=u.position.slice()}return e.ignoreRootClip||null==a||null==r||n.setClipPath(new yM({shape:{x:0,y:0,width:a,height:r}})),{root:n,width:a,height:r,viewBoxRect:l,viewBoxTransform:u}},$r.prototype._parseNode=function(t,e){var i=t.nodeName.toLowerCase();"defs"===i?this._isDefine=!0:"text"===i&&(this._isText=!0);var n;if(this._isDefine){if(r=bT[i]){var o=r.call(this,t),a=t.getAttribute("id");a&&(this._defs[a]=o)}}else{var r=wT[i];r&&(n=r.call(this,t,e),e.add(n))}for(var s=t.firstChild;s;)1===s.nodeType&&this._parseNode(s,n),3===s.nodeType&&this._isText&&this._parseText(s,n),s=s.nextSibling;"defs"===i?this._isDefine=!1:"text"===i&&(this._isText=!1)},$r.prototype._parseText=function(t,e){if(1===t.nodeType){var i=t.getAttribute("dx")||0,n=t.getAttribute("dy")||0;this._textX+=parseFloat(i),this._textY+=parseFloat(n)}var o=new rM({style:{text:t.textContent,transformText:!0},position:[this._textX||0,this._textY||0]});Qr(e,o),es(t,o,this._defs);var a=o.style.fontSize;a&&a<9&&(o.style.fontSize=9,o.scale=o.scale||[1,1],o.scale[0]*=a/9,o.scale[1]*=a/9);var r=o.getBoundingRect();return this._textX+=r.width,e.add(o),o};var wT={g:function(t,e){var i=new tb;return Qr(e,i),es(t,i,this._defs),i},rect:function(t,e){var i=new yM;return Qr(e,i),es(t,i,this._defs),i.setShape({x:parseFloat(t.getAttribute("x")||0),y:parseFloat(t.getAttribute("y")||0),width:parseFloat(t.getAttribute("width")||0),height:parseFloat(t.getAttribute("height")||0)}),i},circle:function(t,e){var i=new sM;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),r:parseFloat(t.getAttribute("r")||0)}),i},line:function(t,e){var i=new _M;return Qr(e,i),es(t,i,this._defs),i.setShape({x1:parseFloat(t.getAttribute("x1")||0),y1:parseFloat(t.getAttribute("y1")||0),x2:parseFloat(t.getAttribute("x2")||0),y2:parseFloat(t.getAttribute("y2")||0)}),i},ellipse:function(t,e){var i=new xT;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),rx:parseFloat(t.getAttribute("rx")||0),ry:parseFloat(t.getAttribute("ry")||0)}),i},polygon:function(t,e){var i=t.getAttribute("points");i&&(i=ts(i));var n=new pM({shape:{points:i||[]}});return Qr(e,n),es(t,n,this._defs),n},polyline:function(t,e){var i=new Pn;Qr(e,i),es(t,i,this._defs);var n=t.getAttribute("points");return n&&(n=ts(n)),new gM({shape:{points:n||[]}})},image:function(t,e){var i=new fi;return Qr(e,i),es(t,i,this._defs),i.setStyle({image:t.getAttribute("xlink:href"),x:t.getAttribute("x"),y:t.getAttribute("y"),width:t.getAttribute("width"),height:t.getAttribute("height")}),i},text:function(t,e){var i=t.getAttribute("x")||0,n=t.getAttribute("y")||0,o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0;this._textX=parseFloat(i)+parseFloat(o),this._textY=parseFloat(n)+parseFloat(a);var r=new tb;return Qr(e,r),es(t,r,this._defs),r},tspan:function(t,e){var i=t.getAttribute("x"),n=t.getAttribute("y");null!=i&&(this._textX=parseFloat(i)),null!=n&&(this._textY=parseFloat(n));var o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0,r=new tb;return Qr(e,r),es(t,r,this._defs),this._textX+=o,this._textY+=a,r},path:function(t,e){var i=Rn(t.getAttribute("d")||"");return Qr(e,i),es(t,i,this._defs),i}},bT={lineargradient:function(t){var e=parseInt(t.getAttribute("x1")||0,10),i=parseInt(t.getAttribute("y1")||0,10),n=parseInt(t.getAttribute("x2")||10,10),o=parseInt(t.getAttribute("y2")||0,10),a=new TM(e,i,n,o);return Jr(t,a),a},radialgradient:function(t){}},ST={fill:"fill",stroke:"stroke","stroke-width":"lineWidth",opacity:"opacity","fill-opacity":"fillOpacity","stroke-opacity":"strokeOpacity","stroke-dasharray":"lineDash","stroke-dashoffset":"lineDashOffset","stroke-linecap":"lineCap","stroke-linejoin":"lineJoin","stroke-miterlimit":"miterLimit","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","text-align":"textAlign","alignment-baseline":"textBaseline"},MT=/url\(\s*#(.*?)\)/,IT=/(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g,TT=/([^\s:;]+)\s*:\s*([^:;]+)/g,AT=R(),DT={registerMap:function(t,e,i){var n;return y(e)?n=e:e.svg?n=[{type:"svg",source:e.svg,specialAreas:e.specialAreas}]:(e.geoJson&&!e.features&&(i=e.specialAreas,e=e.geoJson),n=[{type:"geoJSON",source:e,specialAreas:i}]),d(n,function(t){var e=t.type;"geoJson"===e&&(e=t.type="geoJSON"),(0,CT[e])(t)}),AT.set(t,n)},retrieveMap:function(t){return AT.get(t)}},CT={geoJSON:function(t){var e=t.source;t.geoJSON=_(e)?"undefined"!=typeof JSON&&JSON.parse?JSON.parse(e):new Function("return ("+e+");")():e},svg:function(t){t.svgXML=Kr(t.source)}},LT=k,kT=d,PT=x,NT=w,OT=lI.parseClassType,ET={zrender:"4.0.6"},RT=1e3,zT=1e3,BT=3e3,VT={PROCESSOR:{FILTER:RT,STATISTIC:5e3},VISUAL:{LAYOUT:zT,GLOBAL:2e3,CHART:BT,COMPONENT:4e3,BRUSH:5e3}},GT="__flagInMainProcess",FT="__optionUpdated",WT=/^[a-zA-Z0-9_]+$/;ls.prototype.on=ss("on"),ls.prototype.off=ss("off"),ls.prototype.one=ss("one"),h(ls,fw);var HT=us.prototype;HT._onframe=function(){if(!this._disposed){var t=this._scheduler;if(this[FT]){var e=this[FT].silent;this[GT]=!0,cs(this),ZT.update.call(this),this[GT]=!1,this[FT]=!1,gs.call(this,e),ms.call(this,e)}else if(t.unfinished){var i=1,n=this._model;this._api;t.unfinished=!1;do{var o=+new Date;t.performSeriesTasks(n),t.performDataProcessorTasks(n),fs(this,n),t.performVisualTasks(n),bs(this,this._model,0,"remain"),i-=+new Date-o}while(i>0&&t.unfinished);t.unfinished||this._zr.flush()}}},HT.getDom=function(){return this._dom},HT.getZr=function(){return this._zr},HT.setOption=function(t,e,i){var n;if(NT(e)&&(i=e.lazyUpdate,n=e.silent,e=e.notMerge),this[GT]=!0,!this._model||e){var o=new Wa(this._api),a=this._theme,r=this._model=new MI(null,null,a,o);r.scheduler=this._scheduler,r.init(null,null,a,o)}this._model.setOption(t,qT),i?(this[FT]={silent:n},this[GT]=!1):(cs(this),ZT.update.call(this),this._zr.flush(),this[FT]=!1,this[GT]=!1,gs.call(this,n),ms.call(this,n))},HT.setTheme=function(){console.error("ECharts#setTheme() is DEPRECATED in ECharts 3.0")},HT.getModel=function(){return this._model},HT.getOption=function(){return this._model&&this._model.getOption()},HT.getWidth=function(){return this._zr.getWidth()},HT.getHeight=function(){return this._zr.getHeight()},HT.getDevicePixelRatio=function(){return this._zr.painter.dpr||window.devicePixelRatio||1},HT.getRenderedCanvas=function(t){if(U_.canvasSupported)return(t=t||{}).pixelRatio=t.pixelRatio||1,t.backgroundColor=t.backgroundColor||this._model.get("backgroundColor"),this._zr.painter.getRenderedCanvas(t)},HT.getSvgDataUrl=function(){if(U_.svgSupported){var t=this._zr;return d(t.storage.getDisplayList(),function(t){t.stopAnimation(!0)}),t.painter.pathToDataUrl()}},HT.getDataURL=function(t){var e=(t=t||{}).excludeComponents,i=this._model,n=[],o=this;kT(e,function(t){i.eachComponent({mainType:t},function(t){var e=o._componentsMap[t.__viewId];e.group.ignore||(n.push(e),e.group.ignore=!0)})});var a="svg"===this._zr.painter.getType()?this.getSvgDataUrl():this.getRenderedCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return kT(n,function(t){t.group.ignore=!1}),a},HT.getConnectedDataURL=function(t){if(U_.canvasSupported){var e=this.group,n=Math.min,o=Math.max;if(eA[e]){var a=1/0,r=1/0,s=-1/0,l=-1/0,u=[],h=t&&t.pixelRatio||1;d(tA,function(h,c){if(h.group===e){var d=h.getRenderedCanvas(i(t)),f=h.getDom().getBoundingClientRect();a=n(f.left,a),r=n(f.top,r),s=o(f.right,s),l=o(f.bottom,l),u.push({dom:d,left:f.left,top:f.top})}});var c=(s*=h)-(a*=h),f=(l*=h)-(r*=h),p=iw();p.width=c,p.height=f;var g=Ii(p);return kT(u,function(t){var e=new fi({style:{x:t.left*h-a,y:t.top*h-r,image:t.dom}});g.add(e)}),g.refreshImmediately(),p.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}},HT.convertToPixel=v(hs,"convertToPixel"),HT.convertFromPixel=v(hs,"convertFromPixel"),HT.containPixel=function(t,e){var i;return t=Vi(this._model,t),d(t,function(t,n){n.indexOf("Models")>=0&&d(t,function(t){var o=t.coordinateSystem;if(o&&o.containPoint)i|=!!o.containPoint(e);else if("seriesModels"===n){var a=this._chartsMap[t.__viewId];a&&a.containPoint&&(i|=a.containPoint(e,t))}},this)},this),!!i},HT.getVisual=function(t,e){var i=(t=Vi(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),n=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?i.indexOfRawIndex(t.dataIndex):null;return null!=n?i.getItemVisual(n,e):i.getVisual(e)},HT.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},HT.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var ZT={prepareAndUpdate:function(t){cs(this),ZT.update.call(this,t)},update:function(t){var e=this._model,i=this._api,n=this._zr,o=this._coordSysMgr,a=this._scheduler;if(e){a.restoreData(e,t),a.performSeriesTasks(e),o.create(e,i),a.performDataProcessorTasks(e,t),fs(this,e),o.update(e,i),xs(e),a.performVisualTasks(e,t),_s(this,e,i,t);var r=e.get("backgroundColor")||"transparent";if(U_.canvasSupported)n.setBackgroundColor(r);else{var s=Gt(r);r=qt(s,"rgb"),0===s[3]&&(r="transparent")}Ss(e,i)}},updateTransform:function(t){var e=this._model,i=this,n=this._api;if(e){var o=[];e.eachComponent(function(a,r){var s=i.getViewOfComponentModel(r);if(s&&s.__alive)if(s.updateTransform){var l=s.updateTransform(r,e,n,t);l&&l.update&&o.push(s)}else o.push(s)});var a=R();e.eachSeries(function(o){var r=i._chartsMap[o.__viewId];if(r.updateTransform){var s=r.updateTransform(o,e,n,t);s&&s.update&&a.set(o.uid,1)}else a.set(o.uid,1)}),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0,dirtyMap:a}),bs(i,e,0,t,a),Ss(e,this._api)}},updateView:function(t){var e=this._model;e&&(Ar.markUpdateMethod(t,"updateView"),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0}),_s(this,this._model,this._api,t),Ss(e,this._api))},updateVisual:function(t){ZT.update.call(this,t)},updateLayout:function(t){ZT.update.call(this,t)}};HT.resize=function(t){this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var i=e.resetOption("media"),n=t&&t.silent;this[GT]=!0,i&&cs(this),ZT.update.call(this),this[GT]=!1,gs.call(this,n),ms.call(this,n)}},HT.showLoading=function(t,e){if(NT(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),QT[t]){var i=QT[t](this._api,e),n=this._zr;this._loadingFX=i,n.add(i)}},HT.hideLoading=function(){this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null},HT.makeActionFromEvent=function(t){var e=a({},t);return e.type=jT[t.type],e},HT.dispatchAction=function(t,e){NT(e)||(e={silent:!!e}),XT[t.type]&&this._model&&(this[GT]?this._pendingActions.push(t):(ps.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&U_.browser.weChat&&this._throttledZrFlush(),gs.call(this,e.silent),ms.call(this,e.silent)))},HT.appendData=function(t){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0},HT.on=ss("on"),HT.off=ss("off"),HT.one=ss("one");var UT=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];HT._initEvents=function(){kT(UT,function(t){var e=function(e){var i,n=this.getModel(),o=e.target;if("globalout"===t)i={};else if(o&&null!=o.dataIndex){var r=o.dataModel||n.getSeriesByIndex(o.seriesIndex);i=r&&r.getDataParams(o.dataIndex,o.dataType,o)||{}}else o&&o.eventData&&(i=a({},o.eventData));if(i){var s=i.componentType,l=i.componentIndex;"markLine"!==s&&"markPoint"!==s&&"markArea"!==s||(s="series",l=i.seriesIndex);var u=s&&null!=l&&n.getComponent(s,l),h=u&&this["series"===u.mainType?"_chartsMap":"_componentsMap"][u.__viewId];i.event=e,i.type=t,this._ecEventProcessor.eventInfo={targetEl:o,packedEvent:i,model:u,view:h},this.trigger(t,i)}};e.zrEventfulCallAtLast=!0,this._zr.on(t,e,this)},this),kT(jT,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},HT.isDisposed=function(){return this._disposed},HT.clear=function(){this.setOption({series:[]},!0)},HT.dispose=function(){if(!this._disposed){this._disposed=!0,Fi(this.getDom(),oA,"");var t=this._api,e=this._model;kT(this._componentsViews,function(i){i.dispose(e,t)}),kT(this._chartsViews,function(i){i.dispose(e,t)}),this._zr.dispose(),delete tA[this.id]}},h(us,fw),Ds.prototype={constructor:Ds,normalizeQuery:function(t){var e={},i={},n={};if(_(t)){var o=OT(t);e.mainType=o.main||null,e.subType=o.sub||null}else{var a=["Index","Name","Id"],r={name:1,dataIndex:1,dataType:1};d(t,function(t,o){for(var s=!1,l=0;l0&&h===o.length-u.length){var c=o.slice(0,h);"data"!==c&&(e.mainType=c,e[u.toLowerCase()]=t,s=!0)}}r.hasOwnProperty(o)&&(i[o]=t,s=!0),s||(n[o]=t)})}return{cptQuery:e,dataQuery:i,otherQuery:n}},filter:function(t,e,i){function n(t,e,i,n){return null==t[i]||e[n||i]===t[i]}var o=this.eventInfo;if(!o)return!0;var a=o.targetEl,r=o.packedEvent,s=o.model,l=o.view;if(!s||!l)return!0;var u=e.cptQuery,h=e.dataQuery;return n(u,s,"mainType")&&n(u,s,"subType")&&n(u,s,"index","componentIndex")&&n(u,s,"name")&&n(u,s,"id")&&n(h,r,"name")&&n(h,r,"dataIndex")&&n(h,r,"dataType")&&(!l.filterForExposedEvent||l.filterForExposedEvent(t,e.otherQuery,a,r))},afterTrigger:function(){this.eventInfo=null}};var XT={},jT={},YT=[],qT=[],KT=[],$T=[],JT={},QT={},tA={},eA={},iA=new Date-0,nA=new Date-0,oA="_echarts_instance_",aA=Ls;Bs(2e3,aT),Ns(BI),Os(5e3,function(t){var e=R();t.eachSeries(function(t){var i=t.get("stack");if(i){var n=e.get(i)||e.set(i,[]),o=t.getData(),a={stackResultDimension:o.getCalculationInfo("stackResultDimension"),stackedOverDimension:o.getCalculationInfo("stackedOverDimension"),stackedDimension:o.getCalculationInfo("stackedDimension"),stackedByDimension:o.getCalculationInfo("stackedByDimension"),isStackedByIndex:o.getCalculationInfo("isStackedByIndex"),data:o,seriesModel:t};if(!a.stackedDimension||!a.isStackedByIndex&&!a.stackedByDimension)return;n.length&&o.setCalculationInfo("stackedOnSeries",n[n.length-1].seriesModel),n.push(a)}}),e.each(ar)}),Gs("default",function(t,e){r(e=e||{},{text:"loading",color:"#c23531",textColor:"#000",maskColor:"rgba(255, 255, 255, 0.8)",zlevel:0});var i=new yM({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4}),n=new SM({shape:{startAngle:-lT/2,endAngle:-lT/2+.1,r:10},style:{stroke:e.color,lineCap:"round",lineWidth:5},zlevel:e.zlevel,z:10001}),o=new yM({style:{fill:"none",text:e.text,textPosition:"right",textDistance:10,textFill:e.textColor},zlevel:e.zlevel,z:10001});n.animateShape(!0).when(1e3,{endAngle:3*lT/2}).start("circularInOut"),n.animateShape(!0).when(1e3,{startAngle:3*lT/2}).delay(300).start("circularInOut");var a=new tb;return a.add(n),a.add(o),a.add(i),a.resize=function(){var e=t.getWidth()/2,a=t.getHeight()/2;n.setShape({cx:e,cy:a});var r=n.shape.r;o.setShape({x:e-r,y:a-r,width:2*r,height:2*r}),i.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},a.resize(),a}),Es({type:"highlight",event:"highlight",update:"highlight"},B),Es({type:"downplay",event:"downplay",update:"downplay"},B),Ps("light",mT),Ps("dark",yT);var rA={};Xs.prototype={constructor:Xs,add:function(t){return this._add=t,this},update:function(t){return this._update=t,this},remove:function(t){return this._remove=t,this},execute:function(){var t=this._old,e=this._new,i={},n=[],o=[];for(js(t,{},n,"_oldKeyGetter",this),js(e,i,o,"_newKeyGetter",this),a=0;ax[1]&&(x[1]=y)}e&&(this._nameList[d]=e[f])}this._rawCount=this._count=l,this._extent={},el(this)},yA._initDataFromProvider=function(t,e){if(!(t>=e)){for(var i,n=this._chunkSize,o=this._rawData,a=this._storage,r=this.dimensions,s=r.length,l=this._dimensionInfos,u=this._nameList,h=this._idList,c=this._rawExtent,d=this._nameRepeatCount={},f=this._chunkCount,p=0;pM[1]&&(M[1]=S)}if(!o.pure){var I=u[v];if(m&&null==I)if(null!=m.name)u[v]=I=m.name;else if(null!=i){var T=r[i],A=a[T][y];if(A){I=A[x];var D=l[T].ordinalMeta;D&&D.categories.length&&(I=D.categories[I])}}var C=null==m?null:m.id;null==C&&null!=I&&(d[I]=d[I]||0,C=I,d[I]>0&&(C+="__ec__"+d[I]),d[I]++),null!=C&&(h[v]=C)}}!o.persistent&&o.clean&&o.clean(),this._rawCount=this._count=e,this._extent={},el(this)}},yA.count=function(){return this._count},yA.getIndices=function(){var t=this._indices;if(t){var e=t.constructor,i=this._count;if(e===Array){n=new e(i);for(o=0;o=0&&e=0&&ea&&(a=s)}return i=[o,a],this._extent[t]=i,i},yA.getApproximateExtent=function(t){return t=this.getDimension(t),this._approximateExtent[t]||this.getDataExtent(t)},yA.setApproximateExtent=function(t,e){e=this.getDimension(e),this._approximateExtent[e]=t.slice()},yA.getCalculationInfo=function(t){return this._calculationInfo[t]},yA.setCalculationInfo=function(t,e){lA(t)?a(this._calculationInfo,t):this._calculationInfo[t]=e},yA.getSum=function(t){var e=0;if(this._storage[t])for(var i=0,n=this.count();i=this._rawCount||t<0)return-1;var e=this._indices,i=e[t];if(null!=i&&it))return a;o=a-1}}return-1},yA.indicesOfNearest=function(t,e,i){var n=[];if(!this._storage[t])return n;null==i&&(i=1/0);for(var o=Number.MAX_VALUE,a=-1,r=0,s=this.count();r=0&&a<0)&&(o=u,a=l,n.length=0),n.push(r))}return n},yA.getRawIndex=nl,yA.getRawDataItem=function(t){if(this._rawData.persistent)return this._rawData.getItem(this.getRawIndex(t));for(var e=[],i=0;i=l&&w<=u||isNaN(w))&&(a[r++]=c),c++;h=!0}else if(2===n){for(var d=this._storage[s],v=this._storage[e[1]],y=t[e[1]][0],x=t[e[1]][1],f=0;f=l&&w<=u||isNaN(w))&&(b>=y&&b<=x||isNaN(b))&&(a[r++]=c),c++}h=!0}}if(!h)if(1===n)for(m=0;m=l&&w<=u||isNaN(w))&&(a[r++]=M)}else for(m=0;mt[I][1])&&(S=!1)}S&&(a[r++]=this.getRawIndex(m))}return rb[1]&&(b[1]=w)}}}return o},yA.downSample=function(t,e,i,n){for(var o=sl(this,[t]),a=o._storage,r=[],s=Math.floor(1/e),l=a[t],u=this.count(),h=this._chunkSize,c=o._rawExtent[t],d=new($s(this))(u),f=0,p=0;pu-p&&(s=u-p,r.length=s);for(var g=0;gc[1]&&(c[1]=x),d[f++]=_}return o._count=f,o._indices=d,o.getRawIndex=ol,o},yA.getItemModel=function(t){var e=this.hostModel;return new No(this.getRawDataItem(t),e,e&&e.ecModel)},yA.diff=function(t){var e=this;return new Xs(t?t.getIndices():[],this.getIndices(),function(e){return al(t,e)},function(t){return al(e,t)})},yA.getVisual=function(t){var e=this._visual;return e&&e[t]},yA.setVisual=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setVisual(i,t[i]);else this._visual=this._visual||{},this._visual[t]=e},yA.setLayout=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setLayout(i,t[i]);else this._layout[t]=e},yA.getLayout=function(t){return this._layout[t]},yA.getItemLayout=function(t){return this._itemLayouts[t]},yA.setItemLayout=function(t,e,i){this._itemLayouts[t]=i?a(this._itemLayouts[t]||{},e):e},yA.clearItemLayouts=function(){this._itemLayouts.length=0},yA.getItemVisual=function(t,e,i){var n=this._itemVisuals[t],o=n&&n[e];return null!=o||i?o:this.getVisual(e)},yA.setItemVisual=function(t,e,i){var n=this._itemVisuals[t]||{},o=this.hasItemVisual;if(this._itemVisuals[t]=n,lA(e))for(var a in e)e.hasOwnProperty(a)&&(n[a]=e[a],o[a]=!0);else n[e]=i,o[e]=!0},yA.clearAllVisual=function(){this._visual={},this._itemVisuals=[],this.hasItemVisual={}};var xA=function(t){t.seriesIndex=this.seriesIndex,t.dataIndex=this.dataIndex,t.dataType=this.dataType};yA.setItemGraphicEl=function(t,e){var i=this.hostModel;e&&(e.dataIndex=t,e.dataType=this.dataType,e.seriesIndex=i&&i.seriesIndex,"group"===e.type&&e.traverse(xA,e)),this._graphicEls[t]=e},yA.getItemGraphicEl=function(t){return this._graphicEls[t]},yA.eachItemGraphicEl=function(t,e){d(this._graphicEls,function(i,n){i&&t&&t.call(e,i,n)})},yA.cloneShallow=function(t){if(!t){var e=f(this.dimensions,this.getDimensionInfo,this);t=new vA(e,this.hostModel)}if(t._storage=this._storage,Qs(t,this),this._indices){var i=this._indices.constructor;t._indices=new i(this._indices)}else t._indices=null;return t.getRawIndex=t._indices?ol:nl,t},yA.wrapMethod=function(t,e){var i=this[t];"function"==typeof i&&(this.__wrappedMethods=this.__wrappedMethods||[],this.__wrappedMethods.push(t),this[t]=function(){var t=i.apply(this,arguments);return e.apply(this,[t].concat(C(arguments)))})},yA.TRANSFERABLE_METHODS=["cloneShallow","downSample","map"],yA.CHANGABLE_METHODS=["filterSelf","selectRange"];var _A=function(t,e){return e=e||{},hl(e.coordDimensions||[],t,{dimsDef:e.dimensionsDefine||t.dimensionsDefine,encodeDef:e.encodeDefine||t.encodeDefine,dimCount:e.dimensionsCount,generateCoord:e.generateCoord,generateCoordCount:e.generateCoordCount})};xl.prototype.parse=function(t){return t},xl.prototype.getSetting=function(t){return this._setting[t]},xl.prototype.contain=function(t){var e=this._extent;return t>=e[0]&&t<=e[1]},xl.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},xl.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},xl.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1])},xl.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},xl.prototype.getExtent=function(){return this._extent.slice()},xl.prototype.setExtent=function(t,e){var i=this._extent;isNaN(t)||(i[0]=t),isNaN(e)||(i[1]=e)},xl.prototype.isBlank=function(){return this._isBlank},xl.prototype.setBlank=function(t){this._isBlank=t},xl.prototype.getLabel=null,ji(xl),$i(xl,{registerWhenExtend:!0}),_l.createByAxisModel=function(t){var e=t.option,i=e.data,n=i&&f(i,bl);return new _l({categories:n,needCollect:!n,deduplication:!1!==e.dedplication})};var wA=_l.prototype;wA.getOrdinal=function(t){return wl(this).get(t)},wA.parseAndCollect=function(t){var e,i=this._needCollect;if("string"!=typeof t&&!i)return t;if(i&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var n=wl(this);return null==(e=n.get(t))&&(i?(e=this.categories.length,this.categories[e]=t,n.set(t,e)):e=NaN),e};var bA=xl.prototype,SA=xl.extend({type:"ordinal",init:function(t,e){t&&!y(t)||(t=new _l({categories:t})),this._ordinalMeta=t,this._extent=e||[0,t.categories.length-1]},parse:function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},contain:function(t){return t=this.parse(t),bA.contain.call(this,t)&&null!=this._ordinalMeta.categories[t]},normalize:function(t){return bA.normalize.call(this,this.parse(t))},scale:function(t){return Math.round(bA.scale.call(this,t))},getTicks:function(){for(var t=[],e=this._extent,i=e[0];i<=e[1];)t.push(i),i++;return t},getLabel:function(t){if(!this.isBlank())return this._ordinalMeta.categories[t]},count:function(){return this._extent[1]-this._extent[0]+1},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},getOrdinalMeta:function(){return this._ordinalMeta},niceTicks:B,niceExtent:B});SA.create=function(){return new SA};var MA=Go,IA=Go,TA=xl.extend({type:"interval",_interval:0,_intervalPrecision:2,setExtent:function(t,e){var i=this._extent;isNaN(t)||(i[0]=parseFloat(t)),isNaN(e)||(i[1]=parseFloat(e))},unionExtent:function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),TA.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Ml(t)},getTicks:function(){return Al(this._interval,this._extent,this._niceExtent,this._intervalPrecision)},getLabel:function(t,e){if(null==t)return"";var i=e&&e.precision;return null==i?i=Ho(t)||0:"auto"===i&&(i=this._intervalPrecision),t=IA(t,i,!0),ta(t)},niceTicks:function(t,e,i){t=t||5;var n=this._extent,o=n[1]-n[0];if(isFinite(o)){o<0&&(o=-o,n.reverse());var a=Sl(n,t,e,i);this._intervalPrecision=a.intervalPrecision,this._interval=a.interval,this._niceExtent=a.niceTickExtent}},niceExtent:function(t){var e=this._extent;if(e[0]===e[1])if(0!==e[0]){var i=e[0];t.fixMax?e[0]-=i/2:(e[1]+=i/2,e[0]-=i/2)}else e[1]=1;var n=e[1]-e[0];isFinite(n)||(e[0]=0,e[1]=1),this.niceTicks(t.splitNumber,t.minInterval,t.maxInterval);var o=this._interval;t.fixMin||(e[0]=IA(Math.floor(e[0]/o)*o)),t.fixMax||(e[1]=IA(Math.ceil(e[1]/o)*o))}});TA.create=function(){return new TA};var AA="__ec_stack_",DA="undefined"!=typeof Float32Array?Float32Array:Array,CA={seriesType:"bar",plan:$I(),reset:function(t){if(Rl(t)&&zl(t)){var e=t.getData(),i=t.coordinateSystem,n=i.getBaseAxis(),o=i.getOtherAxis(n),a=e.mapDimension(o.dim),r=e.mapDimension(n.dim),s=o.isHorizontal(),l=s?0:1,u=Ol(Pl([t]),n,t).width;return u>.5||(u=.5),{progress:function(t,e){for(var n,h=new DA(2*t.count),c=[],d=[],f=0;null!=(n=t.next());)d[l]=e.get(a,n),d[1-l]=e.get(r,n),c=i.dataToPoint(d,null,c),h[f++]=c[0],h[f++]=c[1];e.setLayout({largePoints:h,barWidth:u,valueAxisStart:Bl(0,o),valueAxisHorizontal:s})}}}}},LA=TA.prototype,kA=Math.ceil,PA=Math.floor,NA=function(t,e,i,n){for(;i>>1;t[o][1]i&&(a=i);var r=EA.length,s=NA(EA,a,0,r),l=EA[Math.min(s,r-1)],u=l[1];"year"===l[0]&&(u*=$o(o/u/t,!0));var h=this.getSetting("useUTC")?0:60*new Date(+n[0]||+n[1]).getTimezoneOffset()*1e3,c=[Math.round(kA((n[0]-h)/u)*u+h),Math.round(PA((n[1]-h)/u)*u+h)];Tl(c,n),this._stepLvl=l,this._interval=u,this._niceExtent=c},parse:function(t){return+Yo(t)}});d(["contain","normalize"],function(t){OA.prototype[t]=function(e){return LA[t].call(this,this.parse(e))}});var EA=[["hh:mm:ss",1e3],["hh:mm:ss",5e3],["hh:mm:ss",1e4],["hh:mm:ss",15e3],["hh:mm:ss",3e4],["hh:mm\nMM-dd",6e4],["hh:mm\nMM-dd",3e5],["hh:mm\nMM-dd",6e5],["hh:mm\nMM-dd",9e5],["hh:mm\nMM-dd",18e5],["hh:mm\nMM-dd",36e5],["hh:mm\nMM-dd",72e5],["hh:mm\nMM-dd",216e5],["hh:mm\nMM-dd",432e5],["MM-dd\nyyyy",864e5],["MM-dd\nyyyy",1728e5],["MM-dd\nyyyy",2592e5],["MM-dd\nyyyy",3456e5],["MM-dd\nyyyy",432e6],["MM-dd\nyyyy",5184e5],["week",6048e5],["MM-dd\nyyyy",864e6],["week",12096e5],["week",18144e5],["month",26784e5],["week",36288e5],["month",53568e5],["week",6048e6],["quarter",8208e6],["month",107136e5],["month",13392e6],["half-year",16416e6],["month",214272e5],["month",26784e6],["year",32832e6]];OA.create=function(t){return new OA({useUTC:t.ecModel.get("useUTC")})};var RA=xl.prototype,zA=TA.prototype,BA=Ho,VA=Go,GA=Math.floor,FA=Math.ceil,WA=Math.pow,HA=Math.log,ZA=xl.extend({type:"log",base:10,$constructor:function(){xl.apply(this,arguments),this._originalScale=new TA},getTicks:function(){var t=this._originalScale,e=this._extent,i=t.getExtent();return f(zA.getTicks.call(this),function(n){var o=Go(WA(this.base,n));return o=n===e[0]&&t.__fixMin?Vl(o,i[0]):o,o=n===e[1]&&t.__fixMax?Vl(o,i[1]):o},this)},getLabel:zA.getLabel,scale:function(t){return t=RA.scale.call(this,t),WA(this.base,t)},setExtent:function(t,e){var i=this.base;t=HA(t)/HA(i),e=HA(e)/HA(i),zA.setExtent.call(this,t,e)},getExtent:function(){var t=this.base,e=RA.getExtent.call(this);e[0]=WA(t,e[0]),e[1]=WA(t,e[1]);var i=this._originalScale,n=i.getExtent();return i.__fixMin&&(e[0]=Vl(e[0],n[0])),i.__fixMax&&(e[1]=Vl(e[1],n[1])),e},unionExtent:function(t){this._originalScale.unionExtent(t);var e=this.base;t[0]=HA(t[0])/HA(e),t[1]=HA(t[1])/HA(e),RA.unionExtent.call(this,t)},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},niceTicks:function(t){t=t||10;var e=this._extent,i=e[1]-e[0];if(!(i===1/0||i<=0)){var n=qo(i);for(t/i*n<=.5&&(n*=10);!isNaN(n)&&Math.abs(n)<1&&Math.abs(n)>0;)n*=10;var o=[Go(FA(e[0]/n)*n),Go(GA(e[1]/n)*n)];this._interval=n,this._niceExtent=o}},niceExtent:function(t){zA.niceExtent.call(this,t);var e=this._originalScale;e.__fixMin=t.fixMin,e.__fixMax=t.fixMax}});d(["contain","normalize"],function(t){ZA.prototype[t]=function(e){return e=HA(e)/HA(this.base),RA[t].call(this,e)}}),ZA.create=function(){return new ZA};var UA={getMin:function(t){var e=this.option,i=t||null==e.rangeStart?e.min:e.rangeStart;return this.axis&&null!=i&&"dataMin"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getMax:function(t){var e=this.option,i=t||null==e.rangeEnd?e.max:e.rangeEnd;return this.axis&&null!=i&&"dataMax"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getNeedCrossZero:function(){var t=this.option;return null==t.rangeStart&&null==t.rangeEnd&&!t.scale},getCoordSysModel:B,setRange:function(t,e){this.option.rangeStart=t,this.option.rangeEnd=e},resetRange:function(){this.option.rangeStart=this.option.rangeEnd=null}},XA=Un({type:"triangle",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n+a),t.lineTo(i-o,n+a),t.closePath()}}),jA=Un({type:"diamond",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n),t.lineTo(i,n+a),t.lineTo(i-o,n),t.closePath()}}),YA=Un({type:"pin",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.x,n=e.y,o=e.width/5*3,a=Math.max(o,e.height),r=o/2,s=r*r/(a-r),l=n-a+r+s,u=Math.asin(s/r),h=Math.cos(u)*r,c=Math.sin(u),d=Math.cos(u),f=.6*r,p=.7*r;t.moveTo(i-h,l+s),t.arc(i,l,r,Math.PI-u,2*Math.PI+u),t.bezierCurveTo(i+h-c*f,l+s+d*f,i,n-p,i,n),t.bezierCurveTo(i,n-p,i-h+c*f,l+s+d*f,i-h,l+s),t.closePath()}}),qA=Un({type:"arrow",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.height,n=e.width,o=e.x,a=e.y,r=n/3*2;t.moveTo(o,a),t.lineTo(o+r,a+i),t.lineTo(o,a+i/4*3),t.lineTo(o-r,a+i),t.lineTo(o,a),t.closePath()}}),KA={line:function(t,e,i,n,o){o.x1=t,o.y1=e+n/2,o.x2=t+i,o.y2=e+n/2},rect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n},roundRect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n,o.r=Math.min(i,n)/4},square:function(t,e,i,n,o){var a=Math.min(i,n);o.x=t,o.y=e,o.width=a,o.height=a},circle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.r=Math.min(i,n)/2},diamond:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n},pin:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},arrow:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},triangle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n}},$A={};d({line:_M,rect:yM,roundRect:yM,square:yM,circle:sM,diamond:jA,pin:YA,arrow:qA,triangle:XA},function(t,e){$A[e]=new t});var JA=Un({type:"symbol",shape:{symbolType:"",x:0,y:0,width:0,height:0},beforeBrush:function(){var t=this.style;"pin"===this.shape.symbolType&&"inside"===t.textPosition&&(t.textPosition=["50%","40%"],t.textAlign="center",t.textVerticalAlign="middle")},buildPath:function(t,e,i){var n=e.symbolType,o=$A[n];"none"!==e.symbolType&&(o||(o=$A[n="rect"]),KA[n](e.x,e.y,e.width,e.height,o.shape),o.buildPath(t,o.shape,i))}}),QA={isDimensionStacked:pl,enableDataStack:fl,getStackedDimension:gl},tD=(Object.freeze||Object)({createList:function(t){return ml(t.getSource(),t)},getLayoutRect:ca,dataStack:QA,createScale:function(t,e){var i=e;No.isInstance(e)||h(i=new No(e),UA);var n=Hl(i);return n.setExtent(t[0],t[1]),Wl(n,i),n},mixinAxisModelCommonMethods:function(t){h(t,UA)},completeDimensions:hl,createDimensions:_A,createSymbol:Jl}),eD=1e-8;eu.prototype={constructor:eu,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,i=[e,e],n=[-e,-e],o=[],a=[],r=this.geometries,s=0;s0}),function(t){var e=t.properties,i=t.geometry,n=i.coordinates,o=[];"Polygon"===i.type&&o.push({type:"polygon",exterior:n[0],interiors:n.slice(1)}),"MultiPolygon"===i.type&&d(n,function(t){t[0]&&o.push({type:"polygon",exterior:t[0],interiors:t.slice(1)})});var a=new eu(e.name,o,e.cp);return a.properties=e,a})},nD=Bi(),oD=[0,1],aD=function(t,e,i){this.dim=t,this.scale=e,this._extent=i||[0,0],this.inverse=!1,this.onBand=!1};aD.prototype={constructor:aD,contain:function(t){var e=this._extent,i=Math.min(e[0],e[1]),n=Math.max(e[0],e[1]);return t>=i&&t<=n},containData:function(t){return this.contain(this.dataToCoord(t))},getExtent:function(){return this._extent.slice()},getPixelPrecision:function(t){return Zo(t||this.scale.getExtent(),this._extent)},setExtent:function(t,e){var i=this._extent;i[0]=t,i[1]=e},dataToCoord:function(t,e){var i=this._extent,n=this.scale;return t=n.normalize(t),this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count()),Bo(t,oD,i,e)},coordToData:function(t,e){var i=this._extent,n=this.scale;this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count());var o=Bo(t,i,oD,e);return this.scale.scale(o)},pointToData:function(t,e){},getTicksCoords:function(t){var e=(t=t||{}).tickModel||this.getTickModel(),i=au(this,e),n=f(i.ticks,function(t){return{coord:this.dataToCoord(t),tickValue:t}},this),o=e.get("alignWithLabel");return xu(this,n,i.tickCategoryInterval,o,t.clamp),n},getViewLabels:function(){return ou(this).labels},getLabelModel:function(){return this.model.getModel("axisLabel")},getTickModel:function(){return this.model.getModel("axisTick")},getBandWidth:function(){var t=this._extent,e=this.scale.getExtent(),i=e[1]-e[0]+(this.onBand?1:0);0===i&&(i=1);var n=Math.abs(t[1]-t[0]);return Math.abs(n)/i},isHorizontal:null,getRotate:null,calculateCategoryInterval:function(){return pu(this)}};var rD=iD,sD={};d(["map","each","filter","indexOf","inherits","reduce","filter","bind","curry","isArray","isString","isObject","isFunction","extend","defaults","clone","merge"],function(t){sD[t]=aw[t]});var lD={};d(["extendShape","extendPath","makePath","makeImage","mergePath","resizePath","createIcon","setHoverStyle","setLabelStyle","setTextStyle","setText","getFont","updateProps","initProps","getTransform","clipPointsByRect","clipRectByRect","Group","Image","Text","Circle","Sector","Ring","Polygon","Polyline","Rect","Line","BezierCurve","Arc","IncrementalDisplayable","CompoundPath","LinearGradient","RadialGradient","BoundingRect"],function(t){lD[t]=zM[t]}),YI.extend({type:"series.line",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,clipOverflow:!0,label:{position:"top"},lineStyle:{width:2,type:"solid"},step:!1,smooth:!1,smoothMonotone:null,symbol:"emptyCircle",symbolSize:4,symbolRotate:null,showSymbol:!0,showAllSymbol:"auto",connectNulls:!1,sampling:"none",animationEasing:"linear",progressive:0,hoverLayerThreshold:1/0}});var uD=wu.prototype,hD=wu.getSymbolSize=function(t,e){var i=t.getItemVisual(e,"symbolSize");return i instanceof Array?i.slice():[+i,+i]};uD._createSymbol=function(t,e,i,n,o){this.removeAll();var a=Jl(t,-1,-1,2,2,e.getItemVisual(i,"color"),o);a.attr({z2:100,culling:!0,scale:bu(n)}),a.drift=Su,this._symbolType=t,this.add(a)},uD.stopSymbolAnimation=function(t){this.childAt(0).stopAnimation(t)},uD.getSymbolPath=function(){return this.childAt(0)},uD.getScale=function(){return this.childAt(0).scale},uD.highlight=function(){this.childAt(0).trigger("emphasis")},uD.downplay=function(){this.childAt(0).trigger("normal")},uD.setZ=function(t,e){var i=this.childAt(0);i.zlevel=t,i.z=e},uD.setDraggable=function(t){var e=this.childAt(0);e.draggable=t,e.cursor=t?"move":"pointer"},uD.updateData=function(t,e,i){this.silent=!1;var n=t.getItemVisual(e,"symbol")||"circle",o=t.hostModel,a=hD(t,e),r=n!==this._symbolType;if(r){var s=t.getItemVisual(e,"symbolKeepAspect");this._createSymbol(n,t,e,a,s)}else(l=this.childAt(0)).silent=!1,Io(l,{scale:bu(a)},o,e);if(this._updateCommon(t,e,a,i),r){var l=this.childAt(0),u=i&&i.fadeIn,h={scale:l.scale.slice()};u&&(h.style={opacity:l.style.opacity}),l.scale=[0,0],u&&(l.style.opacity=0),To(l,h,o,e)}this._seriesModel=o};var cD=["itemStyle"],dD=["emphasis","itemStyle"],fD=["label"],pD=["emphasis","label"];uD._updateCommon=function(t,e,i,n){var o=this.childAt(0),r=t.hostModel,s=t.getItemVisual(e,"color");"image"!==o.type&&o.useStyle({strokeNoScale:!0});var l=n&&n.itemStyle,u=n&&n.hoverItemStyle,h=n&&n.symbolRotate,c=n&&n.symbolOffset,d=n&&n.labelModel,f=n&&n.hoverLabelModel,p=n&&n.hoverAnimation,g=n&&n.cursorStyle;if(!n||t.hasItemOption){var m=n&&n.itemModel?n.itemModel:t.getItemModel(e);l=m.getModel(cD).getItemStyle(["color"]),u=m.getModel(dD).getItemStyle(),h=m.getShallow("symbolRotate"),c=m.getShallow("symbolOffset"),d=m.getModel(fD),f=m.getModel(pD),p=m.getShallow("hoverAnimation"),g=m.getShallow("cursor")}else u=a({},u);var v=o.style;o.attr("rotation",(h||0)*Math.PI/180||0),c&&o.attr("position",[Vo(c[0],i[0]),Vo(c[1],i[1])]),g&&o.attr("cursor",g),o.setColor(s,n&&n.symbolInnerColor),o.setStyle(l);var y=t.getItemVisual(e,"opacity");null!=y&&(v.opacity=y);var x=t.getItemVisual(e,"liftZ"),_=o.__z2Origin;null!=x?null==_&&(o.__z2Origin=o.z2,o.z2+=x):null!=_&&(o.z2=_,o.__z2Origin=null);var w=n&&n.useNameLabel;go(v,u,d,f,{labelFetcher:r,labelDataIndex:e,defaultText:function(e,i){return w?t.getName(e):_u(t,e)},isRectText:!0,autoColor:s}),o.off("mouseover").off("mouseout").off("emphasis").off("normal"),o.hoverStyle=u,fo(o),o.__symbolOriginalScale=bu(i),p&&r.isAnimationEnabled()&&o.on("mouseover",Mu).on("mouseout",Iu).on("emphasis",Tu).on("normal",Au)},uD.fadeOut=function(t,e){var i=this.childAt(0);this.silent=i.silent=!0,!(e&&e.keepLabel)&&(i.style.text=null),Io(i,{style:{opacity:0},scale:[0,0]},this._seriesModel,this.dataIndex,t)},u(wu,tb);var gD=Du.prototype;gD.updateData=function(t,e){e=Lu(e);var i=this.group,n=t.hostModel,o=this._data,a=this._symbolCtor,r=ku(t);o||i.removeAll(),t.diff(o).add(function(n){var o=t.getItemLayout(n);if(Cu(t,o,n,e)){var s=new a(t,n,r);s.attr("position",o),t.setItemGraphicEl(n,s),i.add(s)}}).update(function(s,l){var u=o.getItemGraphicEl(l),h=t.getItemLayout(s);Cu(t,h,s,e)?(u?(u.updateData(t,s,r),Io(u,{position:h},n)):(u=new a(t,s)).attr("position",h),i.add(u),t.setItemGraphicEl(s,u)):i.remove(u)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&e.fadeOut(function(){i.remove(e)})}).execute(),this._data=t},gD.isPersistent=function(){return!0},gD.updateLayout=function(){var t=this._data;t&&t.eachItemGraphicEl(function(e,i){var n=t.getItemLayout(i);e.attr("position",n)})},gD.incrementalPrepareUpdate=function(t){this._seriesScope=ku(t),this._data=null,this.group.removeAll()},gD.incrementalUpdate=function(t,e,i){i=Lu(i);for(var n=t.start;n0&&Ru(i[o-1]);o--);for(;n0&&Ru(i[a-1]);a--);for(;o=0){var r=o.getItemGraphicEl(a);if(!r){var s=o.getItemLayout(a);if(!s)return;(r=new wu(o,a)).position=s,r.setZ(t.get("zlevel"),t.get("z")),r.ignore=isNaN(s[0])||isNaN(s[1]),r.__temp=!0,o.setItemGraphicEl(a,r),r.stopSymbolAnimation(!0),this.group.add(r)}r.highlight()}else Ar.prototype.highlight.call(this,t,e,i,n)},downplay:function(t,e,i,n){var o=t.getData(),a=zi(o,n);if(null!=a&&a>=0){var r=o.getItemGraphicEl(a);r&&(r.__temp?(o.setItemGraphicEl(a,null),this.group.remove(r)):r.downplay())}else Ar.prototype.downplay.call(this,t,e,i,n)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new MD({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e,e},_newPolygon:function(t,e){var i=this._polygon;return i&&this._lineGroup.remove(i),i=new ID({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(i),this._polygon=i,i},_updateAnimation:function(t,e,i,n,o,a){var r=this._polyline,s=this._polygon,l=t.hostModel,u=mD(this._data,t,this._stackedOnPoints,e,this._coordSys,i,this._valueOrigin,a),h=u.current,c=u.stackedOnCurrent,d=u.next,f=u.stackedOnNext;o&&(h=Yu(u.current,i,o),c=Yu(u.stackedOnCurrent,i,o),d=Yu(u.next,i,o),f=Yu(u.stackedOnNext,i,o)),r.shape.__points=u.current,r.shape.points=h,Io(r,{shape:{points:d}},l),s&&(s.setShape({points:h,stackedOnPoints:c}),Io(s,{shape:{points:d,stackedOnPoints:f}},l));for(var p=[],g=u.status,m=0;me&&(e=t[i]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,i=0;ie[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},u(kD,aD);var PD={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},ND={};ND.categoryAxis=n({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},PD),ND.valueAxis=n({boundaryGap:[0,0],splitNumber:5},PD),ND.timeAxis=r({scale:!0,min:"dataMin",max:"dataMax"},ND.valueAxis),ND.logAxis=r({scale:!0,logBase:10},ND.valueAxis);var OD=["value","category","time","log"],ED=function(t,e,i,a){d(OD,function(r){e.extend({type:t+"Axis."+r,mergeDefaultAndTheme:function(e,o){var a=this.layoutMode,s=a?ga(e):{};n(e,o.getTheme().get(r+"Axis")),n(e,this.getDefaultOption()),e.type=i(t,e),a&&pa(e,s,a)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=_l.createByAxisModel(this))},getCategories:function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:o([{},ND[r+"Axis"],a],!0)})}),lI.registerSubTypeDefaulter(t+"Axis",v(i,t))},RD=lI.extend({type:"cartesian2dAxis",axis:null,init:function(){RD.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){RD.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){RD.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});n(RD.prototype,UA);var zD={offset:0};ED("x",RD,th,zD),ED("y",RD,th,zD),lI.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var BD=ih.prototype;BD.type="grid",BD.axisPointerEnabled=!0,BD.getRect=function(){return this._rect},BD.update=function(t,e){var i=this._axesMap;this._updateScale(t,this.model),d(i.x,function(t){Wl(t.scale,t.model)}),d(i.y,function(t){Wl(t.scale,t.model)});var n={};d(i.x,function(t){nh(i,"y",t,n)}),d(i.y,function(t){nh(i,"x",t,n)}),this.resize(this.model,e)},BD.resize=function(t,e,i){function n(){d(a,function(t){var e=t.isHorizontal(),i=e?[0,o.width]:[0,o.height],n=t.inverse?1:0;t.setExtent(i[n],i[1-n]),ah(t,e?o.x:o.y)})}var o=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()});this._rect=o;var a=this._axesList;n(),!i&&t.get("containLabel")&&(d(a,function(t){if(!t.model.get("axisLabel.inside")){var e=jl(t);if(e){var i=t.isHorizontal()?"height":"width",n=t.model.get("axisLabel.margin");o[i]-=e[i]+n,"top"===t.position?o.y+=e.height+n:"left"===t.position&&(o.x+=e.width+n)}}}),n())},BD.getAxis=function(t,e){var i=this._axesMap[t];if(null!=i){if(null==e)for(var n in i)if(i.hasOwnProperty(n))return i[n];return i[e]}},BD.getAxes=function(){return this._axesList.slice()},BD.getCartesian=function(t,e){if(null!=t&&null!=e){var i="x"+t+"y"+e;return this._coordsMap[i]}w(t)&&(e=t.yAxisIndex,t=t.xAxisIndex);for(var n=0,o=this._coordsList;nu[1]?-1:1,c=["start"===o?u[0]-h*l:"end"===o?u[1]+h*l:(u[0]+u[1])/2,ph(o)?t.labelOffset+r*l:0],d=e.get("nameRotate");null!=d&&(d=d*GD/180);var f;ph(o)?n=HD(t.rotation,null!=d?d:t.rotation,r):(n=uh(t,o,d||0,u),null!=(f=t.axisNameAvailableWidth)&&(f=Math.abs(f/Math.sin(n.rotation)),!isFinite(f)&&(f=null)));var p=s.getFont(),g=e.get("nameTruncate",!0)||{},m=g.ellipsis,v=T(t.nameTruncateMaxWidth,g.maxWidth,f),y=null!=m&&null!=v?tI(i,v,p,m,{minChar:2,placeholder:g.placeholder}):i,x=e.get("tooltip",!0),_=e.mainType,w={componentType:_,name:i,$vars:["name"]};w[_+"Index"]=e.componentIndex;var b=new rM({anid:"name",__fullText:i,__truncatedText:y,position:c,rotation:n.rotation,silent:hh(e),z2:1,tooltip:x&&x.show?a({content:i,formatter:function(){return i},formatterParams:w},x):null});mo(b.style,s,{text:y,textFont:p,textFill:s.getTextColor()||e.get("axisLine.lineStyle.color"),textAlign:n.textAlign,textVerticalAlign:n.textVerticalAlign}),e.get("triggerEvent")&&(b.eventData=lh(e),b.eventData.targetType="axisName",b.eventData.name=i),this._dumbGroup.add(b),b.updateTransform(),this.group.add(b),b.decomposeTransform()}}},HD=FD.innerTextLayout=function(t,e,i){var n,o,a=Xo(e-t);return jo(a)?(o=i>0?"top":"bottom",n="center"):jo(a-GD)?(o=i>0?"bottom":"top",n="center"):(o="middle",n=a>0&&a0?"right":"left":i>0?"left":"right"),{rotation:a,textAlign:n,textVerticalAlign:o}},ZD=d,UD=v,XD=Ws({type:"axis",_axisPointer:null,axisPointerClass:null,render:function(t,e,i,n){this.axisPointerClass&&Sh(t),XD.superApply(this,"render",arguments),Dh(this,t,0,i,0,!0)},updateAxisPointer:function(t,e,i,n,o){Dh(this,t,0,i,0,!1)},remove:function(t,e){var i=this._axisPointer;i&&i.remove(e),XD.superApply(this,"remove",arguments)},dispose:function(t,e){Ch(this,e),XD.superApply(this,"dispose",arguments)}}),jD=[];XD.registerAxisPointerClass=function(t,e){jD[t]=e},XD.getAxisPointerClass=function(t){return t&&jD[t]};var YD=["axisLine","axisTickLabel","axisName"],qD=["splitArea","splitLine"],KD=XD.extend({type:"cartesianAxis",axisPointerClass:"CartesianAxisPointer",render:function(t,e,i,n){this.group.removeAll();var o=this._axisGroup;if(this._axisGroup=new tb,this.group.add(this._axisGroup),t.get("show")){var a=t.getCoordSysModel(),r=Lh(a,t),s=new FD(t,r);d(YD,s.add,s),this._axisGroup.add(s.getGroup()),d(qD,function(e){t.get(e+".show")&&this["_"+e](t,a)},this),Lo(o,this._axisGroup,t),KD.superCall(this,"render",t,e,i,n)}},remove:function(){this._splitAreaColors=null},_splitLine:function(t,e){var i=t.axis;if(!i.scale.isBlank()){var n=t.getModel("splitLine"),o=n.getModel("lineStyle"),a=o.get("color");a=y(a)?a:[a];for(var s=e.coordinateSystem.getRect(),l=i.isHorizontal(),u=0,h=i.getTicksCoords({tickModel:n}),c=[],d=[],f=o.getLineStyle(),p=0;p1){var c;"string"==typeof o?c=DD[o]:"function"==typeof o&&(c=o),c&&t.setData(n.downSample(n.mapDimension(s.dim),1/h,c,CD))}}}}}("line"));var $D=YI.extend({type:"series.__base_bar__",getInitialData:function(t,e){return ml(this.getSource(),this)},getMarkerPosition:function(t){var e=this.coordinateSystem;if(e){var i=e.dataToPoint(e.clampData(t)),n=this.getData(),o=n.getLayout("offset"),a=n.getLayout("size");return i[e.getBaseAxis().isHorizontal()?0:1]+=o+a/2,i}return[NaN,NaN]},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,large:!1,largeThreshold:400,progressive:3e3,progressiveChunkMode:"mod",itemStyle:{},emphasis:{}}});$D.extend({type:"series.bar",dependencies:["grid","polar"],brushSelector:"rect",getProgressive:function(){return!!this.get("large")&&this.get("progressive")},getProgressiveThreshold:function(){var t=this.get("progressiveThreshold"),e=this.get("largeThreshold");return e>t&&(t=e),t}});var JD=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["stroke","barBorderColor"],["lineWidth","barBorderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),QD={getBarItemStyle:function(t){var e=JD(this,t);if(this.getBorderLineDash){var i=this.getBorderLineDash();i&&(e.lineDash=i)}return e}},tC=["itemStyle","barBorderWidth"];a(No.prototype,QD),Zs({type:"bar",render:function(t,e,i){this._updateDrawMode(t);var n=t.get("coordinateSystem");return"cartesian2d"!==n&&"polar"!==n||(this._isLargeDraw?this._renderLarge(t,e,i):this._renderNormal(t,e,i)),this.group},incrementalPrepareRender:function(t,e,i){this._clear(),this._updateDrawMode(t)},incrementalRender:function(t,e,i,n){this._incrementalRenderLarge(t,e)},_updateDrawMode:function(t){var e=t.pipelineContext.large;(null==this._isLargeDraw||e^this._isLargeDraw)&&(this._isLargeDraw=e,this._clear())},_renderNormal:function(t,e,i){var n,o=this.group,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.getBaseAxis();"cartesian2d"===s.type?n=l.isHorizontal():"polar"===s.type&&(n="angle"===l.dim);var u=t.isAnimationEnabled()?t:null;a.diff(r).add(function(e){if(a.hasValue(e)){var i=a.getItemModel(e),r=iC[s.type](a,e,i),l=eC[s.type](a,e,i,r,n,u);a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,i,r,t,n,"polar"===s.type)}}).update(function(e,i){var l=r.getItemGraphicEl(i);if(a.hasValue(e)){var h=a.getItemModel(e),c=iC[s.type](a,e,h);l?Io(l,{shape:c},u,e):l=eC[s.type](a,e,h,c,n,u,!0),a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,h,c,t,n,"polar"===s.type)}else o.remove(l)}).remove(function(t){var e=r.getItemGraphicEl(t);"cartesian2d"===s.type?e&&Nh(t,u,e):e&&Oh(t,u,e)}).execute(),this._data=a},_renderLarge:function(t,e,i){this._clear(),zh(t,this.group)},_incrementalRenderLarge:function(t,e){zh(e,this.group,!0)},dispose:B,remove:function(t){this._clear(t)},_clear:function(t){var e=this.group,i=this._data;t&&t.get("animation")&&i&&!this._isLargeDraw?i.eachItemGraphicEl(function(e){"sector"===e.type?Oh(e.dataIndex,t,e):Nh(e.dataIndex,t,e)}):e.removeAll(),this._data=null}});var eC={cartesian2d:function(t,e,i,n,o,r,s){var l=new yM({shape:a({},n)});if(r){var u=l.shape,h=o?"height":"width",c={};u[h]=0,c[h]=n[h],zM[s?"updateProps":"initProps"](l,{shape:c},r,e)}return l},polar:function(t,e,i,n,o,a,s){var l=n.startAngle0?1:-1,r=n.height>0?1:-1;return{x:n.x+a*o/2,y:n.y+r*o/2,width:n.width-a*o,height:n.height-r*o}},polar:function(t,e,i){var n=t.getItemLayout(e);return{cx:n.cx,cy:n.cy,r0:n.r0,r:n.r,startAngle:n.startAngle,endAngle:n.endAngle}}},nC=Pn.extend({type:"largeBar",shape:{points:[]},buildPath:function(t,e){for(var i=e.points,n=this.__startPoint,o=this.__valueIdx,a=0;a0&&"scale"!==u){var d=o.getItemLayout(0),f=Math.max(i.getWidth(),i.getHeight())/2,p=m(r.removeClipPath,r);r.setClipPath(this._createClipPath(d.cx,d.cy,f,d.startAngle,d.clockwise,p,t))}else r.removeClipPath();this._data=o}},dispose:function(){},_createClipPath:function(t,e,i,n,o,a,r){var s=new hM({shape:{cx:t,cy:e,r0:0,r:i,startAngle:n,endAngle:n,clockwise:o}});return To(s,{shape:{endAngle:n+(o?1:-1)*Math.PI*2}},r,a),s},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var lC=function(t,e){d(e,function(e){e.update="updateView",Es(e,function(i,n){var o={};return n.eachComponent({mainType:"series",subType:t,query:i},function(t){t[e.method]&&t[e.method](i.name,i.dataIndex);var n=t.getData();n.each(function(e){var i=n.getName(e);o[i]=t.isSelected(i)||!1})}),{name:i.name,selected:o}})})},uC=function(t){return{getTargetSeries:function(e){var i={},n=R();return e.eachSeriesByType(t,function(t){t.__paletteScope=i,n.set(t.uid,t)}),n},reset:function(t,e){var i=t.getRawData(),n={},o=t.getData();o.each(function(t){var e=o.getRawIndex(t);n[e]=t}),i.each(function(e){var a=n[e],r=null!=a&&o.getItemVisual(a,"color",!0);if(r)i.setItemVisual(e,"color",r);else{var s=i.getItemModel(e).get("itemStyle.color")||t.getColorFromPalette(i.getName(e)||e+"",t.__paletteScope,i.count());i.setItemVisual(e,"color",s),null!=a&&o.setItemVisual(a,"color",s)}})}}},hC=function(t,e,i,n){var o,a,r=t.getData(),s=[],l=!1;r.each(function(i){var n,u,h,c,d=r.getItemLayout(i),f=r.getItemModel(i),p=f.getModel("label"),g=p.get("position")||f.get("emphasis.label.position"),m=f.getModel("labelLine"),v=m.get("length"),y=m.get("length2"),x=(d.startAngle+d.endAngle)/2,_=Math.cos(x),w=Math.sin(x);o=d.cx,a=d.cy;var b="inside"===g||"inner"===g;if("center"===g)n=d.cx,u=d.cy,c="center";else{var S=(b?(d.r+d.r0)/2*_:d.r*_)+o,M=(b?(d.r+d.r0)/2*w:d.r*w)+a;if(n=S+3*_,u=M+3*w,!b){var I=S+_*(v+e-d.r),T=M+w*(v+e-d.r),A=I+(_<0?-1:1)*y,D=T;n=A+(_<0?-5:5),u=D,h=[[S,M],[I,T],[A,D]]}c=b?"center":_>0?"left":"right"}var C=p.getFont(),L=p.get("rotate")?_<0?-x+Math.PI:-x:0,k=ke(t.getFormattedLabel(i,"normal")||r.getName(i),C,c,"top");l=!!L,d.label={x:n,y:u,position:g,height:k.height,len:v,len2:y,linePoints:h,textAlign:c,verticalAlign:"middle",rotation:L,inside:b},b||s.push(d.label)}),!l&&t.get("avoidLabelOverlap")&&Hh(s,o,a,e,i,n)},cC=2*Math.PI,dC=Math.PI/180,fC=function(t){return{seriesType:t,reset:function(t,e){var i=e.findComponents({mainType:"legend"});if(i&&i.length){var n=t.getData();n.filterSelf(function(t){for(var e=n.getName(t),o=0;o=0;s--){var l=2*s,u=n[l]-a/2,h=n[l+1]-r/2;if(t>=u&&e>=h&&t<=u+a&&e<=h+r)return s}return-1}}),gC=Uh.prototype;gC.isPersistent=function(){return!this._incremental},gC.updateData=function(t){this.group.removeAll();var e=new pC({rectHover:!0,cursor:"default"});e.setShape({points:t.getLayout("symbolPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},gC.updateLayout=function(t){if(!this._incremental){var e=t.getLayout("symbolPoints");this.group.eachChild(function(t){if(null!=t.startIndex){var i=2*(t.endIndex-t.startIndex),n=4*t.startIndex*2;e=new Float32Array(e.buffer,n,i)}t.setShape("points",e)})}},gC.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>2e6?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},gC.incrementalUpdate=function(t,e){var i;this._incremental?(i=new pC,this._incremental.addDisplayable(i,!0)):((i=new pC({rectHover:!0,cursor:"default",startIndex:t.start,endIndex:t.end})).incremental=!0,this.group.add(i)),i.setShape({points:e.getLayout("symbolPoints")}),this._setCommon(i,e,!!this._incremental)},gC._setCommon=function(t,e,i){var n=e.hostModel,o=e.getVisual("symbolSize");t.setShape("size",o instanceof Array?o:[o,o]),t.symbolProxy=Jl(e.getVisual("symbol"),0,0,0,0),t.setColor=t.symbolProxy.setColor;var a=t.shape.size[0]<4;t.useStyle(n.getModel("itemStyle").getItemStyle(a?["color","shadowBlur","shadowColor"]:["color"]));var r=e.getVisual("color");r&&t.setColor(r),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>=0&&(t.dataIndex=i+(t.startIndex||0))}))},gC.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},gC._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},Zs({type:"scatter",render:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).updateData(n),this._finished=!0},incrementalPrepareRender:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).incrementalPrepareUpdate(n),this._finished=!1},incrementalRender:function(t,e,i){this._symbolDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},updateTransform:function(t,e,i){var n=t.getData();if(this.group.dirty(),!this._finished||n.count()>1e4||!this._symbolDraw.isPersistent())return{update:!0};var o=AD().reset(t);o.progress&&o.progress({start:0,end:n.count()},n),this._symbolDraw.updateLayout(n)},_updateSymbolDraw:function(t,e){var i=this._symbolDraw,n=e.pipelineContext.large;return i&&n===this._isLargeDraw||(i&&i.remove(),i=this._symbolDraw=n?new Uh:new Du,this._isLargeDraw=n,this.group.removeAll()),this.group.add(i.group),i},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},dispose:function(){}}),Bs(TD("scatter","circle")),zs(AD("scatter")),u(Xh,aD),jh.prototype.getIndicatorAxes=function(){return this._indicatorAxes},jh.prototype.dataToPoint=function(t,e){var i=this._indicatorAxes[e];return this.coordToPoint(i.dataToCoord(t),e)},jh.prototype.coordToPoint=function(t,e){var i=this._indicatorAxes[e].angle;return[this.cx+t*Math.cos(i),this.cy-t*Math.sin(i)]},jh.prototype.pointToData=function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=Math.sqrt(e*e+i*i);e/=n,i/=n;for(var o,a=Math.atan2(-i,e),r=1/0,s=-1,l=0;ln[0]&&isFinite(c)&&isFinite(n[0]))}else{r.getTicks().length-1>a&&(u=i(u));var d=Math.round((n[0]+n[1])/2/u)*u,f=Math.round(a/2);r.setExtent(Go(d-f*u),Go(d+(a-f)*u)),r.setInterval(u)}})},jh.dimensions=[],jh.create=function(t,e){var i=[];return t.eachComponent("radar",function(n){var o=new jh(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeriesByType("radar",function(t){"radar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("radarIndex")||0])}),i},Fa.register("radar",jh);var mC=ND.valueAxis,vC=(Fs({type:"radar",optionUpdated:function(){var t=this.get("boundaryGap"),e=this.get("splitNumber"),o=this.get("scale"),s=this.get("axisLine"),l=this.get("axisTick"),u=this.get("axisLabel"),h=this.get("name"),c=this.get("name.show"),d=this.get("name.formatter"),p=this.get("nameGap"),g=this.get("triggerEvent"),m=f(this.get("indicator")||[],function(f){null!=f.max&&f.max>0&&!f.min?f.min=0:null!=f.min&&f.min<0&&!f.max&&(f.max=0);var m=h;if(null!=f.color&&(m=r({color:f.color},h)),f=n(i(f),{boundaryGap:t,splitNumber:e,scale:o,axisLine:s,axisTick:l,axisLabel:u,name:f.text,nameLocation:"end",nameGap:p,nameTextStyle:m,triggerEvent:g},!1),c||(f.name=""),"string"==typeof d){var v=f.name;f.name=d.replace("{value}",null!=v?v:"")}else"function"==typeof d&&(f.name=d(f.name,f));var y=a(new No(f,null,this.ecModel),UA);return y.mainType="radar",y.componentIndex=this.componentIndex,y},this);this.getIndicatorModels=function(){return m}},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"75%",startAngle:90,name:{show:!0},boundaryGap:[0,0],splitNumber:5,nameGap:15,scale:!1,shape:"polygon",axisLine:n({lineStyle:{color:"#bbb"}},mC.axisLine),axisLabel:Yh(mC.axisLabel,!1),axisTick:Yh(mC.axisTick,!1),splitLine:Yh(mC.splitLine,!0),splitArea:Yh(mC.splitArea,!0),indicator:[]}}),["axisLine","axisTickLabel","axisName"]);Ws({type:"radar",render:function(t,e,i){this.group.removeAll(),this._buildAxes(t),this._buildSplitLineAndArea(t)},_buildAxes:function(t){var e=t.coordinateSystem;d(f(e.getIndicatorAxes(),function(t){return new FD(t.model,{position:[e.cx,e.cy],rotation:t.angle,labelDirection:-1,tickDirection:-1,nameDirection:1})}),function(t){d(vC,t.add,t),this.group.add(t.getGroup())},this)},_buildSplitLineAndArea:function(t){function e(t,e,i){var n=i%e.length;return t[n]=t[n]||[],n}var i=t.coordinateSystem,n=i.getIndicatorAxes();if(n.length){var o=t.get("shape"),a=t.getModel("splitLine"),s=t.getModel("splitArea"),l=a.getModel("lineStyle"),u=s.getModel("areaStyle"),h=a.get("show"),c=s.get("show"),p=l.get("color"),g=u.get("color");p=y(p)?p:[p],g=y(g)?g:[g];var m=[],v=[];if("circle"===o)for(var x=n[0].getTicksCoords(),_=i.cx,w=i.cy,b=0;b"+f(i,function(i,n){var o=e.get(e.mapDimension(i.dim),t);return ia(i.name+" : "+o)}).join("
")},defaultOption:{zlevel:0,z:2,coordinateSystem:"radar",legendHoverLink:!0,radarIndex:0,lineStyle:{width:2,type:"solid"},label:{position:"top"},symbol:"emptyCircle",symbolSize:4}});Zs({type:"radar",render:function(t,e,n){function o(t,e){var i=t.getItemVisual(e,"symbol")||"circle",n=t.getItemVisual(e,"color");if("none"!==i){var o=qh(t.getItemVisual(e,"symbolSize")),a=Jl(i,-1,-1,2,2,n);return a.attr({style:{strokeNoScale:!0},z2:100,scale:[o[0]/2,o[1]/2]}),a}}function a(e,i,n,a,r,s){n.removeAll();for(var l=0;l"+ia(n+" : "+i)},getTooltipPosition:function(t){if(null!=t){var e=this.getData().getName(t),i=this.coordinateSystem,n=i.getRegion(e);return n&&i.dataToPoint(n.center)}},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},defaultOption:{zlevel:0,z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:.75,showLegendSymbol:!0,dataRangeHoverLink:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",areaColor:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{areaColor:"rgba(255,215,0,0.8)"}}}}),aC);var EC="\0_ec_interaction_mutex";Es({type:"takeGlobalCursor",event:"globalCursorTaken",update:"update"},function(){}),h(oc,fw);var RC={axisPointer:1,tooltip:1,brush:1};xc.prototype={constructor:xc,draw:function(t,e,i,n,o){var a="geo"===t.mainType,r=t.getData&&t.getData();a&&e.eachComponent({mainType:"series",subType:"map"},function(e){r||e.getHostGeoModel()!==t||(r=e.getData())});var s=t.coordinateSystem;this._updateBackground(s);var l=this._regionsGroup,u=this.group,h=s.scale,c={position:s.position,scale:h};!l.childAt(0)||o?u.attr(c):Io(u,c,t),l.removeAll();var f=["itemStyle"],p=["emphasis","itemStyle"],g=["label"],m=["emphasis","label"],v=R();d(s.regions,function(e){var i=v.get(e.name)||v.set(e.name,new tb),n=new MM({shape:{paths:[]}});i.add(n);var o,s=(C=t.getRegionModel(e.name)||t).getModel(f),u=C.getModel(p),c=mc(s),y=mc(u),x=C.getModel(g),_=C.getModel(m);if(r){o=r.indexOfName(e.name);var w=r.getItemVisual(o,"color",!0);w&&(c.fill=w)}d(e.geometries,function(t){if("polygon"===t.type){n.shape.paths.push(new pM({shape:{points:t.exterior}}));for(var e=0;e<(t.interiors?t.interiors.length:0);e++)n.shape.paths.push(new pM({shape:{points:t.interiors[e]}}))}}),n.setStyle(c),n.style.strokeNoScale=!0,n.culling=!0;var b=x.get("show"),S=_.get("show"),M=r&&isNaN(r.get(r.mapDimension("value"),o)),I=r&&r.getItemLayout(o);if(a||M&&(b||S)||I&&I.showLabel){var T,A=a?e.name:o;(!r||o>=0)&&(T=t);var D=new rM({position:e.center.slice(),scale:[1/h[0],1/h[1]],z2:10,silent:!0});go(D.style,D.hoverStyle={},x,_,{labelFetcher:T,labelDataIndex:A,defaultText:e.name,useInsideStyle:!1},{textAlign:"center",textVerticalAlign:"middle"}),i.add(D)}if(r)r.setItemGraphicEl(o,i);else{var C=t.getRegionModel(e.name);n.eventData={componentType:"geo",componentIndex:t.componentIndex,geoIndex:t.componentIndex,name:e.name,region:C&&C.option||{}}}(i.__regions||(i.__regions=[])).push(e),fo(i,y,{hoverSilentOnTouch:!!t.get("selectedMode")}),l.add(i)}),this._updateController(t,e,i),vc(this,t,l,i,n),yc(t,l)},remove:function(){this._regionsGroup.removeAll(),this._backgroundGroup.removeAll(),this._controller.dispose(),this._mapName&&OC.removeGraphic(this._mapName,this.uid),this._mapName=null,this._controllerHost={}},_updateBackground:function(t){var e=t.map;this._mapName!==e&&d(OC.makeGraphic(e,this.uid),function(t){this._backgroundGroup.add(t)},this),this._mapName=e},_updateController:function(t,e,i){function n(){var e={type:"geoRoam",componentType:l};return e[l+"Id"]=t.id,e}var o=t.coordinateSystem,r=this._controller,s=this._controllerHost;s.zoomLimit=t.get("scaleLimit"),s.zoom=o.getZoom(),r.enable(t.get("roam")||!1);var l=t.mainType;r.off("pan").on("pan",function(t){this._mouseDownFlag=!1,fc(s,t.dx,t.dy),i.dispatchAction(a(n(),{dx:t.dx,dy:t.dy}))},this),r.off("zoom").on("zoom",function(t){if(this._mouseDownFlag=!1,pc(s,t.scale,t.originX,t.originY),i.dispatchAction(a(n(),{zoom:t.scale,originX:t.originX,originY:t.originY})),this._updateGroup){var e=this.group.scale;this._regionsGroup.traverse(function(t){"text"===t.type&&t.attr("scale",[1/e[0],1/e[1]])})}},this),r.setPointerChecker(function(e,n,a){return o.getViewRectAfterRoam().contain(n,a)&&!gc(e,i,t)})}};var zC="__seriesMapHighDown",BC="__seriesMapCallKey";Zs({type:"map",render:function(t,e,i,n){if(!n||"mapToggleSelect"!==n.type||n.from!==this.uid){var o=this.group;if(o.removeAll(),!t.getHostGeoModel()){if(n&&"geoRoam"===n.type&&"series"===n.componentType&&n.seriesId===t.id)(a=this._mapDraw)&&o.add(a.group);else if(t.needsDrawMap){var a=this._mapDraw||new xc(i,!0);o.add(a.group),a.draw(t,e,i,this,n),this._mapDraw=a}else this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null;t.get("showLegendSymbol")&&e.getComponent("legend")&&this._renderSymbols(t,e,i)}}},remove:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null,this.group.removeAll()},dispose:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null},_renderSymbols:function(t,e,i){var n=t.originalData,o=this.group;n.each(n.mapDimension("value"),function(e,i){if(!isNaN(e)){var r=n.getItemLayout(i);if(r&&r.point){var s=r.point,l=r.offset,u=new sM({style:{fill:t.getData().getVisual("color")},shape:{cx:s[0]+9*l,cy:s[1],r:3},silent:!0,z2:8+(l?0:NM+1)});if(!l){var h=t.mainSeries.getData(),c=n.getName(i),d=h.indexOfName(c),f=n.getItemModel(i),p=f.getModel("label"),g=f.getModel("emphasis.label"),m=h.getItemGraphicEl(d),y=A(t.getFormattedLabel(d,"normal"),c),x=A(t.getFormattedLabel(d,"emphasis"),y),_=m[zC],w=Math.random();if(!_){_=m[zC]={};var b=v(_c,!0),S=v(_c,!1);m.on("mouseover",b).on("mouseout",S).on("emphasis",b).on("normal",S)}m[BC]=w,a(_,{recordVersion:w,circle:u,labelModel:p,hoverLabelModel:g,emphasisText:x,normalText:y}),wc(_,!1)}o.add(u)}}})}}),Es({type:"geoRoam",event:"geoRoam",update:"updateTransform"},function(t,e){var i=t.componentType||"series";e.eachComponent({mainType:i,query:t},function(e){var n=e.coordinateSystem;if("geo"===n.type){var o=bc(n,t,e.get("scaleLimit"));e.setCenter&&e.setCenter(o.center),e.setZoom&&e.setZoom(o.zoom),"series"===i&&d(e.seriesGroup,function(t){t.setCenter(o.center),t.setZoom(o.zoom)})}})});var VC=Q;h(Sc,Tw),Mc.prototype={constructor:Mc,type:"view",dimensions:["x","y"],setBoundingRect:function(t,e,i,n){return this._rect=new de(t,e,i,n),this._rect},getBoundingRect:function(){return this._rect},setViewRect:function(t,e,i,n){this.transformTo(t,e,i,n),this._viewRect=new de(t,e,i,n)},transformTo:function(t,e,i,n){var o=this.getBoundingRect(),a=this._rawTransformable;a.transform=o.calculateTransform(new de(t,e,i,n)),a.decomposeTransform(),this._updateTransform()},setCenter:function(t){t&&(this._center=t,this._updateCenterAndZoom())},setZoom:function(t){t=t||1;var e=this.zoomLimit;e&&(null!=e.max&&(t=Math.min(e.max,t)),null!=e.min&&(t=Math.max(e.min,t))),this._zoom=t,this._updateCenterAndZoom()},getDefaultCenter:function(){var t=this.getBoundingRect();return[t.x+t.width/2,t.y+t.height/2]},getCenter:function(){return this._center||this.getDefaultCenter()},getZoom:function(){return this._zoom||1},getRoamTransform:function(){return this._roamTransformable.getLocalTransform()},_updateCenterAndZoom:function(){var t=this._rawTransformable.getLocalTransform(),e=this._roamTransformable,i=this.getDefaultCenter(),n=this.getCenter(),o=this.getZoom();n=Q([],n,t),i=Q([],i,t),e.origin=n,e.position=[i[0]-n[0],i[1]-n[1]],e.scale=[o,o],this._updateTransform()},_updateTransform:function(){var t=this._roamTransformable,e=this._rawTransformable;e.parent=t,t.updateTransform(),e.updateTransform(),wt(this.transform||(this.transform=[]),e.transform||xt()),this._rawTransform=e.getLocalTransform(),this.invTransform=this.invTransform||[],Tt(this.invTransform,this.transform),this.decomposeTransform()},getViewRect:function(){return this._viewRect},getViewRectAfterRoam:function(){var t=this.getBoundingRect().clone();return t.applyTransform(this.transform),t},dataToPoint:function(t,e,i){var n=e?this._rawTransform:this.transform;return i=i||[],n?VC(i,t,n):G(i,t)},pointToData:function(t){var e=this.invTransform;return e?VC([],t,e):[t[0],t[1]]},convertToPixel:v(Ic,"dataToPoint"),convertFromPixel:v(Ic,"pointToData"),containPoint:function(t){return this.getViewRectAfterRoam().contain(t[0],t[1])}},h(Mc,Tw),Tc.prototype={constructor:Tc,type:"geo",dimensions:["lng","lat"],containCoord:function(t){for(var e=this.regions,i=0;ie&&(e=n.height)}this.height=e+1},getNodeById:function(t){if(this.getId()===t)return this;for(var e=0,i=this.children,n=i.length;e=0&&this.hostTree.data.setItemLayout(this.dataIndex,t,e)},getLayout:function(){return this.hostTree.data.getItemLayout(this.dataIndex)},getModel:function(t){if(!(this.dataIndex<0)){var e,i=this.hostTree,n=i.data.getItemModel(this.dataIndex),o=this.getLevelModel();return o||0!==this.children.length&&(0===this.children.length||!1!==this.isExpand)||(e=this.getLeavesModel()),n.getModel(t,(o||e||i.hostModel).getModel(t))}},getLevelModel:function(){return(this.hostTree.levelModels||[])[this.depth]},getLeavesModel:function(){return this.hostTree.leavesModel},setVisual:function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemVisual(this.dataIndex,t,e)},getVisual:function(t,e){return this.hostTree.data.getItemVisual(this.dataIndex,t,e)},getRawIndex:function(){return this.hostTree.data.getRawIndex(this.dataIndex)},getId:function(){return this.hostTree.data.getId(this.dataIndex)},isAncestorOf:function(t){for(var e=t.parentNode;e;){if(e===this)return!0;e=e.parentNode}return!1},isDescendantOf:function(t){return t!==this&&t.isAncestorOf(this)}},Vc.prototype={constructor:Vc,type:"tree",eachNode:function(t,e,i){this.root.eachNode(t,e,i)},getNodeByDataIndex:function(t){var e=this.data.getRawIndex(t);return this._nodes[e]},getNodeByName:function(t){return this.root.getNodeByName(t)},update:function(){for(var t=this.data,e=this._nodes,i=0,n=e.length;ia&&(a=t.depth)});var r=t.expandAndCollapse&&t.initialTreeDepth>=0?t.initialTreeDepth:a;return o.root.eachNode("preorder",function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=r}),o.data},getOrient:function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},formatTooltip:function(t){for(var e=this.getData().tree,i=e.root.children[0],n=e.getNodeByDataIndex(t),o=n.getValue(),a=n.name;n&&n!==i;)a=n.parentNode.name+"."+a,n=n.parentNode;return ia(a+(isNaN(o)||null==o?"":" : "+o))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0,color:"#555"},leaves:{label:{show:!0}},animationEasing:"linear",animationDuration:700,animationDurationUpdate:1e3}}),Zs({type:"tree",init:function(t,e){this._oldTree,this._mainGroup=new tb,this._controller=new oc(e.getZr()),this._controllerHost={target:this.group},this.group.add(this._mainGroup)},render:function(t,e,i,n){var o=t.getData(),a=t.layoutInfo,r=this._mainGroup,s=t.get("layout");"radial"===s?r.attr("position",[a.x+a.width/2,a.y+a.height/2]):r.attr("position",[a.x,a.y]),this._updateViewCoordSys(t),this._updateController(t,e,i);var l=this._data,u={expandAndCollapse:t.get("expandAndCollapse"),layout:s,orient:t.getOrient(),curvature:t.get("lineStyle.curveness"),symbolRotate:t.get("symbolRotate"),symbolOffset:t.get("symbolOffset"),hoverAnimation:t.get("hoverAnimation"),useNameLabel:!0,fadeIn:!0};o.diff(l).add(function(e){td(o,e)&&id(o,e,null,r,t,u)}).update(function(e,i){var n=l.getItemGraphicEl(i);td(o,e)?id(o,e,n,r,t,u):n&&nd(l,i,n,r,t,u)}).remove(function(e){var i=l.getItemGraphicEl(e);i&&nd(l,e,i,r,t,u)}).execute(),this._nodeScaleRatio=t.get("nodeScaleRatio"),this._updateNodeAndLinkScale(t),!0===u.expandAndCollapse&&o.eachItemGraphicEl(function(e,n){e.off("click").on("click",function(){i.dispatchAction({type:"treeExpandAndCollapse",seriesId:t.id,dataIndex:n})})}),this._data=o},_updateViewCoordSys:function(t){var e=t.getData(),i=[];e.each(function(t){var n=e.getItemLayout(t);!n||isNaN(n.x)||isNaN(n.y)||i.push([+n.x,+n.y])});var n=[],o=[];fn(i,n,o),o[0]-n[0]==0&&(o[0]+=1,n[0]-=1),o[1]-n[1]==0&&(o[1]+=1,n[1]-=1);var a=t.coordinateSystem=new Mc;a.zoomLimit=t.get("scaleLimit"),a.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1]),a.setCenter(t.get("center")),a.setZoom(t.get("zoom")),this.group.attr({position:a.position,scale:a.scale}),this._viewCoordSys=a},_updateController:function(t,e,i){var n=this._controller,o=this._controllerHost,a=this.group;n.setPointerChecker(function(e,n,o){var r=a.getBoundingRect();return r.applyTransform(a.transform),r.contain(n,o)&&!gc(e,i,t)}),n.enable(t.get("roam")),o.zoomLimit=t.get("scaleLimit"),o.zoom=t.coordinateSystem.getZoom(),n.off("pan").off("zoom").on("pan",function(e){fc(o,e.dx,e.dy),i.dispatchAction({seriesId:t.id,type:"treeRoam",dx:e.dx,dy:e.dy})},this).on("zoom",function(e){pc(o,e.scale,e.originX,e.originY),i.dispatchAction({seriesId:t.id,type:"treeRoam",zoom:e.scale,originX:e.originX,originY:e.originY}),this._updateNodeAndLinkScale(t)},this)},_updateNodeAndLinkScale:function(t){var e=t.getData(),i=this._getNodeGlobalScale(t),n=[i,i];e.eachItemGraphicEl(function(t,e){t.attr("scale",n)})},_getNodeGlobalScale:function(t){var e=t.coordinateSystem;if("view"!==e.type)return 1;var i=this._nodeScaleRatio,n=e.scale,o=n&&n[0]||1;return((e.getZoom()-1)*i+1)/o},dispose:function(){this._controller&&this._controller.dispose(),this._controllerHost={}},remove:function(){this._mainGroup.removeAll(),this._data=null}}),Es({type:"treeExpandAndCollapse",event:"treeExpandAndCollapse",update:"update"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=t.dataIndex,n=e.getData().tree.getNodeByDataIndex(i);n.isExpand=!n.isExpand})}),Es({type:"treeRoam",event:"treeRoam",update:"none"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=bc(e.coordinateSystem,t);e.setCenter&&e.setCenter(i.center),e.setZoom&&e.setZoom(i.zoom)})});Bs(TD("tree","circle")),zs(function(t,e){t.eachSeriesByType("tree",function(t){sd(t,e)})}),YI.extend({type:"series.treemap",layoutMode:"box",dependencies:["grid","polar"],_viewRoot:null,defaultOption:{progressive:0,hoverLayerThreshold:1/0,left:"center",top:"middle",right:null,bottom:null,width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",borderColor:"rgba(255,255,255,0.7)",borderWidth:1,shadowColor:"rgba(150,150,150,1)",shadowBlur:3,shadowOffsetX:0,shadowOffsetY:0,textStyle:{color:"#fff"}},emphasis:{textStyle:{}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",ellipsis:!0},upperLabel:{show:!1,position:[0,"50%"],height:20,color:"#fff",ellipsis:!0,verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],color:"#fff",ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},getInitialData:function(t,e){var i={name:t.name,children:t.data};dd(i);var n=t.levels||[];n=t.levels=fd(n,e);var o={};return o.levels=n,Vc.createTree(i,this,o).data},optionUpdated:function(){this.resetViewRoot()},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=ta(y(i)?i[0]:i);return ia(e.getName(t)+": "+n)},getDataParams:function(t){var e=YI.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=cd(i,this),e},setLayoutInfo:function(t){this.layoutInfo=this.layoutInfo||{},a(this.layoutInfo,t)},mapIdToIndex:function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=R(),this._idIndexMapCount=0);var i=e.get(t);return null==i&&e.set(t,i=this._idIndexMapCount++),i},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var UC=5;pd.prototype={constructor:pd,render:function(t,e,i,n){var o=t.getModel("breadcrumb"),a=this.group;if(a.removeAll(),o.get("show")&&i){var r=o.getModel("itemStyle"),s=r.getModel("textStyle"),l={pos:{left:o.get("left"),right:o.get("right"),top:o.get("top"),bottom:o.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:o.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(i,l,s),this._renderContent(t,l,r,s,n),da(a,l.pos,l.box)}},_prepare:function(t,e,i){for(var n=t;n;n=n.parentNode){var o=n.getModel().get("name"),a=i.getTextRect(o),r=Math.max(a.width+16,e.emptyItemWidth);e.totalWidth+=r+8,e.renderList.push({node:n,text:o,width:r})}},_renderContent:function(t,e,i,n,o){for(var a=0,s=e.emptyItemWidth,l=t.get("breadcrumb.height"),u=ha(e.pos,e.box),h=e.totalWidth,c=e.renderList,d=c.length-1;d>=0;d--){var f=c[d],p=f.node,g=f.width,m=f.text;h>u.width&&(h-=g-s,g=s,m=null);var y=new pM({shape:{points:gd(a,0,g,l,d===c.length-1,0===d)},style:r(i.getItemStyle(),{lineJoin:"bevel",text:m,textFill:n.getTextColor(),textFont:n.getFont()}),z:10,onclick:v(o,p)});this.group.add(y),md(y,t,p),a+=g+8}},remove:function(){this.group.removeAll()}};var XC=m,jC=tb,YC=yM,qC=d,KC=["label"],$C=["emphasis","label"],JC=["upperLabel"],QC=["emphasis","upperLabel"],tL=10,eL=1,iL=2,nL=Qb([["fill","color"],["stroke","strokeColor"],["lineWidth","strokeWidth"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),oL=function(t){var e=nL(t);return e.stroke=e.fill=e.lineWidth=null,e};Zs({type:"treemap",init:function(t,e){this._containerGroup,this._storage={nodeGroup:[],background:[],content:[]},this._oldTree,this._breadcrumb,this._controller,this._state="ready"},render:function(t,e,i,n){if(!(l(e.findComponents({mainType:"series",subType:"treemap",query:n}),t)<0)){this.seriesModel=t,this.api=i,this.ecModel=e;var o=ld(n,["treemapZoomToNode","treemapRootToNode"],t),a=n&&n.type,r=t.layoutInfo,s=!this._oldTree,u=this._storage,h="treemapRootToNode"===a&&o&&u?{rootNodeGroup:u.nodeGroup[o.node.getRawIndex()],direction:n.direction}:null,c=this._giveContainerGroup(r),d=this._doRender(c,t,h);s||a&&"treemapZoomToNode"!==a&&"treemapRootToNode"!==a?d.renderFinally():this._doAnimation(c,d,t,h),this._resetController(i),this._renderBreadcrumb(t,i,o)}},_giveContainerGroup:function(t){var e=this._containerGroup;return e||(e=this._containerGroup=new jC,this._initEvents(e),this.group.add(e)),e.attr("position",[t.x,t.y]),e},_doRender:function(t,e,i){function n(t,e,i,o,a){function r(t){return t.getId()}function s(r,s){var l=null!=r?t[r]:null,u=null!=s?e[s]:null,c=h(l,u,i,a);c&&n(l&&l.viewChildren||[],u&&u.viewChildren||[],c,o,a+1)}o?(e=t,qC(t,function(t,e){!t.isRemoved()&&s(e,e)})):new Xs(e,t,r,r).add(s).update(s).remove(v(s,null)).execute()}var o=e.getData().tree,a=this._oldTree,r={nodeGroup:[],background:[],content:[]},s={nodeGroup:[],background:[],content:[]},l=this._storage,u=[],h=v(yd,e,s,l,i,r,u);n(o.root?[o.root]:[],a&&a.root?[a.root]:[],t,o===a||!a,0);var c=function(t){var e={nodeGroup:[],background:[],content:[]};return t&&qC(t,function(t,i){var n=e[i];qC(t,function(t){t&&(n.push(t),t.__tmWillDelete=1)})}),e}(l);return this._oldTree=o,this._storage=s,{lastsForAnimation:r,willDeleteEls:c,renderFinally:function(){qC(c,function(t){qC(t,function(t){t.parent&&t.parent.remove(t)})}),qC(u,function(t){t.invisible=!0,t.dirty()})}}},_doAnimation:function(t,e,i,n){if(i.get("animation")){var o=i.get("animationDurationUpdate"),r=i.get("animationEasing"),s=vd();qC(e.willDeleteEls,function(t,e){qC(t,function(t,i){if(!t.invisible){var a,l=t.parent;if(n&&"drillDown"===n.direction)a=l===n.rootNodeGroup?{shape:{x:0,y:0,width:l.__tmNodeWidth,height:l.__tmNodeHeight},style:{opacity:0}}:{style:{opacity:0}};else{var u=0,h=0;l.__tmWillDelete||(u=l.__tmNodeWidth/2,h=l.__tmNodeHeight/2),a="nodeGroup"===e?{position:[u,h],style:{opacity:0}}:{shape:{x:u,y:h,width:0,height:0},style:{opacity:0}}}a&&s.add(t,a,o,r)}})}),qC(this._storage,function(t,i){qC(t,function(t,n){var l=e.lastsForAnimation[i][n],u={};l&&("nodeGroup"===i?l.old&&(u.position=t.position.slice(),t.attr("position",l.old)):(l.old&&(u.shape=a({},t.shape),t.setShape(l.old)),l.fadein?(t.setStyle("opacity",0),u.style={opacity:1}):1!==t.style.opacity&&(u.style={opacity:1})),s.add(t,u,o,r))})},this),this._state="animating",s.done(XC(function(){this._state="ready",e.renderFinally()},this)).start()}},_resetController:function(t){var e=this._controller;e||((e=this._controller=new oc(t.getZr())).enable(this.seriesModel.get("roam")),e.on("pan",XC(this._onPan,this)),e.on("zoom",XC(this._onZoom,this)));var i=new de(0,0,t.getWidth(),t.getHeight());e.setPointerChecker(function(t,e,n){return i.contain(e,n)})},_clearController:function(){var t=this._controller;t&&(t.dispose(),t=null)},_onPan:function(t){if("animating"!==this._state&&(Math.abs(t.dx)>3||Math.abs(t.dy)>3)){var e=this.seriesModel.getData().tree.root;if(!e)return;var i=e.getLayout();if(!i)return;this.api.dispatchAction({type:"treemapMove",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:i.x+t.dx,y:i.y+t.dy,width:i.width,height:i.height}})}},_onZoom:function(t){var e=t.originX,i=t.originY;if("animating"!==this._state){var n=this.seriesModel.getData().tree.root;if(!n)return;var o=n.getLayout();if(!o)return;var a=new de(o.x,o.y,o.width,o.height),r=this.seriesModel.layoutInfo;e-=r.x,i-=r.y;var s=xt();St(s,s,[-e,-i]),It(s,s,[t.scale,t.scale]),St(s,s,[e,i]),a.applyTransform(s),this.api.dispatchAction({type:"treemapRender",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:a.x,y:a.y,width:a.width,height:a.height}})}},_initEvents:function(t){t.on("click",function(t){if("ready"===this._state){var e=this.seriesModel.get("nodeClick",!0);if(e){var i=this.findTarget(t.offsetX,t.offsetY);if(i){var n=i.node;if(n.getLayout().isLeafRoot)this._rootToNode(i);else if("zoomToNode"===e)this._zoomToNode(i);else if("link"===e){var o=n.hostTree.data.getItemModel(n.dataIndex),a=o.get("link",!0),r=o.get("target",!0)||"blank";a&&window.open(a,r)}}}}},this)},_renderBreadcrumb:function(t,e,i){i||(i=null!=t.get("leafDepth",!0)?{node:t.getViewRoot()}:this.findTarget(e.getWidth()/2,e.getHeight()/2))||(i={node:t.getData().tree.root}),(this._breadcrumb||(this._breadcrumb=new pd(this.group))).render(t,e,i.node,XC(function(e){"animating"!==this._state&&(hd(t.getViewRoot(),e)?this._rootToNode({node:e}):this._zoomToNode({node:e}))},this))},remove:function(){this._clearController(),this._containerGroup&&this._containerGroup.removeAll(),this._storage={nodeGroup:[],background:[],content:[]},this._state="ready",this._breadcrumb&&this._breadcrumb.remove()},dispose:function(){this._clearController()},_zoomToNode:function(t){this.api.dispatchAction({type:"treemapZoomToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},_rootToNode:function(t){this.api.dispatchAction({type:"treemapRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},findTarget:function(t,e){var i;return this.seriesModel.getViewRoot().eachNode({attr:"viewChildren",order:"preorder"},function(n){var o=this._storage.background[n.getRawIndex()];if(o){var a=o.transformCoordToLocal(t,e),r=o.shape;if(!(r.x<=a[0]&&a[0]<=r.x+r.width&&r.y<=a[1]&&a[1]<=r.y+r.height))return!1;i={node:n,offsetX:a[0],offsetY:a[1]}}},this),i}});for(var aL=["treemapZoomToNode","treemapRender","treemapMove"],rL=0;rL=0&&t.call(e,i[o],o)},TL.eachEdge=function(t,e){for(var i=this.edges,n=i.length,o=0;o=0&&i[o].node1.dataIndex>=0&&i[o].node2.dataIndex>=0&&t.call(e,i[o],o)},TL.breadthFirstTraverse=function(t,e,i,n){if(Jd.isInstance(e)||(e=this._nodesMap[$d(e)]),e){for(var o="out"===i?"outEdges":"in"===i?"inEdges":"edges",a=0;a=0&&i.node2.dataIndex>=0});for(var o=0,a=n.length;o=0&&this[t][e].setItemVisual(this.dataIndex,i,n)},getVisual:function(i,n){return this[t][e].getItemVisual(this.dataIndex,i,n)},setLayout:function(i,n){this.dataIndex>=0&&this[t][e].setItemLayout(this.dataIndex,i,n)},getLayout:function(){return this[t][e].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[t][e].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[t][e].getRawIndex(this.dataIndex)}}};h(Jd,AL("hostGraph","data")),h(Qd,AL("hostGraph","edgeData")),IL.Node=Jd,IL.Edge=Qd,Yi(Jd),Yi(Qd);var DL=function(t,e,i,n,o){for(var a=new IL(n),r=0;r "+f)),h++)}var p,g=i.get("coordinateSystem");if("cartesian2d"===g||"polar"===g)p=ml(t,i);else{var m=Fa.get(g),v=m&&"view"!==m.type?m.dimensions||[]:[];l(v,"value")<0&&v.concat(["value"]);var y=_A(t,{coordDimensions:v});(p=new vA(y,i)).initData(t)}var x=new vA(["value"],i);return x.initData(u,s),o&&o(p,x),kc({mainData:p,struct:a,structAttr:"graph",datas:{node:p,edge:x},datasAttr:{node:"data",edge:"edgeData"}}),a.update(),a},CL=Hs({type:"series.graph",init:function(t){CL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this._categoriesData},this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeOption:function(t){CL.superApply(this,"mergeOption",arguments),this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeDefaultAndTheme:function(t){CL.superApply(this,"mergeDefaultAndTheme",arguments),Ci(t,["edgeLabel"],["show"])},getInitialData:function(t,e){var i=t.edges||t.links||[],n=t.data||t.nodes||[],o=this;if(n&&i)return DL(n,i,this,!0,function(t,i){function n(t){return(t=this.parsePath(t))&&"label"===t[0]?r:t&&"emphasis"===t[0]&&"label"===t[1]?l:this.parentModel}t.wrapMethod("getItemModel",function(t){var e=o._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t});var a=o.getModel("edgeLabel"),r=new No({label:a.option},a.parentModel,e),s=o.getModel("emphasis.edgeLabel"),l=new No({emphasis:{label:s.option}},s.parentModel,e);i.wrapMethod("getItemModel",function(t){return t.customizeGetParent(n),t})}).data},getGraph:function(){return this.getData().graph},getEdgeData:function(){return this.getGraph().edgeData},getCategoriesData:function(){return this._categoriesData},formatTooltip:function(t,e,i){if("edge"===i){var n=this.getData(),o=this.getDataParams(t,i),a=n.graph.getEdgeByIndex(t),r=n.getName(a.node1.dataIndex),s=n.getName(a.node2.dataIndex),l=[];return null!=r&&l.push(r),null!=s&&l.push(s),l=ia(l.join(" > ")),o.value&&(l+=" : "+ia(o.value)),l}return CL.superApply(this,"formatTooltip",arguments)},_updateCategoriesData:function(){var t=f(this.option.categories||[],function(t){return null!=t.value?t:a({value:0},t)}),e=new vA(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray(function(t){return e.getItemModel(t,!0)})},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},isAnimationEnabled:function(){return CL.superCall(this,"isAnimationEnabled")&&!("force"===this.get("layout")&&this.get("force.layoutAnimation"))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,hoverAnimation:!0,layout:null,focusNodeAdjacency:!1,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle"},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,curveness:0,opacity:.5},emphasis:{label:{show:!0}}}}),LL=_M.prototype,kL=bM.prototype,PL=Un({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){(tf(e)?LL:kL).buildPath(t,e)},pointAt:function(t){return tf(this.shape)?LL.pointAt.call(this,t):kL.pointAt.call(this,t)},tangentAt:function(t){var e=this.shape,i=tf(e)?[e.x2-e.x1,e.y2-e.y1]:kL.tangentAt.call(this,t);return q(i,i)}}),NL=["fromSymbol","toSymbol"],OL=rf.prototype;OL.beforeUpdate=function(){var t=this,e=t.childOfName("fromSymbol"),i=t.childOfName("toSymbol"),n=t.childOfName("label");if(e||i||!n.ignore){for(var o=1,a=this.parent;a;)a.scale&&(o/=a.scale[0]),a=a.parent;var r=t.childOfName("line");if(this.__dirty||r.__dirty){var s=r.shape.percent,l=r.pointAt(0),u=r.pointAt(s),h=U([],u,l);if(q(h,h),e&&(e.attr("position",l),c=r.tangentAt(0),e.attr("rotation",Math.PI/2-Math.atan2(c[1],c[0])),e.attr("scale",[o*s,o*s])),i){i.attr("position",u);var c=r.tangentAt(1);i.attr("rotation",-Math.PI/2-Math.atan2(c[1],c[0])),i.attr("scale",[o*s,o*s])}if(!n.ignore){n.attr("position",u);var d,f,p,g=5*o;if("end"===n.__position)d=[h[0]*g+u[0],h[1]*g+u[1]],f=h[0]>.8?"left":h[0]<-.8?"right":"center",p=h[1]>.8?"top":h[1]<-.8?"bottom":"middle";else if("middle"===n.__position){var m=s/2,v=[(c=r.tangentAt(m))[1],-c[0]],y=r.pointAt(m);v[1]>0&&(v[0]=-v[0],v[1]=-v[1]),d=[y[0]+v[0]*g,y[1]+v[1]*g],f="center",p="bottom";var x=-Math.atan2(c[1],c[0]);u[0].8?"right":h[0]<-.8?"left":"center",p=h[1]>.8?"bottom":h[1]<-.8?"top":"middle";n.attr({style:{textVerticalAlign:n.__verticalAlign||p,textAlign:n.__textAlign||f},position:d,scale:[o,o]})}}}},OL._createLine=function(t,e,i){var n=t.hostModel,o=of(t.getItemLayout(e));o.shape.percent=0,To(o,{shape:{percent:1}},n,e),this.add(o);var a=new rM({name:"label",lineLabelOriginalOpacity:1});this.add(a),d(NL,function(i){var n=nf(i,t,e);this.add(n),this[ef(i)]=t.getItemVisual(e,i)},this),this._updateCommonStl(t,e,i)},OL.updateData=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=t.getItemLayout(e),r={shape:{}};af(r.shape,a),Io(o,r,n,e),d(NL,function(i){var n=t.getItemVisual(e,i),o=ef(i);if(this[o]!==n){this.remove(this.childOfName(i));var a=nf(i,t,e);this.add(a)}this[o]=n},this),this._updateCommonStl(t,e,i)},OL._updateCommonStl=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=i&&i.lineStyle,s=i&&i.hoverLineStyle,l=i&&i.labelModel,u=i&&i.hoverLabelModel;if(!i||t.hasItemOption){var h=t.getItemModel(e);a=h.getModel("lineStyle").getLineStyle(),s=h.getModel("emphasis.lineStyle").getLineStyle(),l=h.getModel("label"),u=h.getModel("emphasis.label")}var c=t.getItemVisual(e,"color"),f=D(t.getItemVisual(e,"opacity"),a.opacity,1);o.useStyle(r({strokeNoScale:!0,fill:"none",stroke:c,opacity:f},a)),o.hoverStyle=s,d(NL,function(t){var e=this.childOfName(t);e&&(e.setColor(c),e.setStyle({opacity:f}))},this);var p,g,m=l.getShallow("show"),v=u.getShallow("show"),y=this.childOfName("label");if((m||v)&&(p=c||"#000",null==(g=n.getFormattedLabel(e,"normal",t.dataType)))){var x=n.getRawValue(e);g=null==x?t.getName(e):isFinite(x)?Go(x):x}var _=m?g:null,w=v?A(n.getFormattedLabel(e,"emphasis",t.dataType),g):null,b=y.style;null==_&&null==w||(mo(y.style,l,{text:_},{autoColor:p}),y.__textAlign=b.textAlign,y.__verticalAlign=b.textVerticalAlign,y.__position=l.get("position")||"middle"),y.hoverStyle=null!=w?{text:w,textFill:u.getTextColor(!0),fontStyle:u.getShallow("fontStyle"),fontWeight:u.getShallow("fontWeight"),fontSize:u.getShallow("fontSize"),fontFamily:u.getShallow("fontFamily")}:{text:null},y.ignore=!m&&!v,fo(this)},OL.highlight=function(){this.trigger("emphasis")},OL.downplay=function(){this.trigger("normal")},OL.updateLayout=function(t,e){this.setLinePoints(t.getItemLayout(e))},OL.setLinePoints=function(t){var e=this.childOfName("line");af(e.shape,t),e.dirty()},u(rf,tb);var EL=sf.prototype;EL.isPersistent=function(){return!0},EL.updateData=function(t){var e=this,i=e.group,n=e._lineData;e._lineData=t,n||i.removeAll();var o=hf(t);t.diff(n).add(function(i){lf(e,t,i,o)}).update(function(i,a){uf(e,n,t,a,i,o)}).remove(function(t){i.remove(n.getItemGraphicEl(t))}).execute()},EL.updateLayout=function(){var t=this._lineData;t&&t.eachItemGraphicEl(function(e,i){e.updateLayout(t,i)},this)},EL.incrementalPrepareUpdate=function(t){this._seriesScope=hf(t),this._lineData=null,this.group.removeAll()},EL.incrementalUpdate=function(t,e){for(var i=t.start;i=o/3?1:2),l=e.y-n(r)*a*(a>=o/3?1:2);r=e.angle-Math.PI/2,t.moveTo(s,l),t.lineTo(e.x+i(r)*a,e.y+n(r)*a),t.lineTo(e.x+i(e.angle)*o,e.y+n(e.angle)*o),t.lineTo(e.x-i(r)*a,e.y-n(r)*a),t.lineTo(s,l)}}),YL=2*Math.PI,qL=(Ar.extend({type:"gauge",render:function(t,e,i){this.group.removeAll();var n=t.get("axisLine.lineStyle.color"),o=Sf(t,i);this._renderMain(t,e,i,n,o)},dispose:function(){},_renderMain:function(t,e,i,n,o){for(var a=this.group,r=t.getModel("axisLine").getModel("lineStyle"),s=t.get("clockwise"),l=-t.get("startAngle")/180*Math.PI,u=-t.get("endAngle")/180*Math.PI,h=(u-l)%YL,c=l,d=r.get("width"),f=0;f=t&&(0===e?0:n[e-1][0]).4?"bottom":"middle",textAlign:A<-.4?"left":A>.4?"right":"center"},{autoColor:P}),silent:!0}))}if(g.get("show")&&T!==v){for(var N=0;N<=y;N++){var A=Math.cos(w),D=Math.sin(w),O=new _M({shape:{x1:A*c+u,y1:D*c+h,x2:A*(c-_)+u,y2:D*(c-_)+h},silent:!0,style:I});"auto"===I.stroke&&O.setStyle({stroke:n((T+N/y)/v)}),l.add(O),w+=S}w-=S}else w+=b}},_renderPointer:function(t,e,i,n,o,a,r,s){var l=this.group,u=this._data;if(t.get("pointer.show")){var h=[+t.get("min"),+t.get("max")],c=[a,r],d=t.getData(),f=d.mapDimension("value");d.diff(u).add(function(e){var i=new jL({shape:{angle:a}});To(i,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(i),d.setItemGraphicEl(e,i)}).update(function(e,i){var n=u.getItemGraphicEl(i);Io(n,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(n),d.setItemGraphicEl(e,n)}).remove(function(t){var e=u.getItemGraphicEl(t);l.remove(e)}).execute(),d.eachItemGraphicEl(function(t,e){var i=d.getItemModel(e),a=i.getModel("pointer");t.setShape({x:o.cx,y:o.cy,width:Vo(a.get("width"),o.r),r:Vo(a.get("length"),o.r)}),t.useStyle(i.getModel("itemStyle").getItemStyle()),"auto"===t.style.fill&&t.setStyle("fill",n(Bo(d.get(f,e),h,[0,1],!0))),fo(t,i.getModel("emphasis.itemStyle").getItemStyle())}),this._data=d}else u&&u.eachItemGraphicEl(function(t){l.remove(t)})},_renderTitle:function(t,e,i,n,o){var a=t.getData(),r=a.mapDimension("value"),s=t.getModel("title");if(s.get("show")){var l=s.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=+t.get("min"),d=+t.get("max"),f=n(Bo(t.getData().get(r,0),[c,d],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},s,{x:u,y:h,text:a.getName(0),textAlign:"center",textVerticalAlign:"middle"},{autoColor:f,forceRich:!0})}))}},_renderDetail:function(t,e,i,n,o){var a=t.getModel("detail"),r=+t.get("min"),s=+t.get("max");if(a.get("show")){var l=a.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=Vo(a.get("width"),o.r),d=Vo(a.get("height"),o.r),f=t.getData(),p=f.get(f.mapDimension("value"),0),g=n(Bo(p,[r,s],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},a,{x:u,y:h,text:Mf(p,a.get("formatter")),textWidth:isNaN(c)?null:c,textHeight:isNaN(d)?null:d,textAlign:"center",textVerticalAlign:"middle"},{autoColor:g,forceRich:!0})}))}}}),Hs({type:"series.funnel",init:function(t){qL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()},this._defaultLabelLine(t)},getInitialData:function(t,e){return oC(this,["value"])},_defaultLabelLine:function(t){Ci(t,"labelLine",["show"]);var e=t.labelLine,i=t.emphasis.labelLine;e.show=e.show&&t.label.show,i.show=i.show&&t.emphasis.label.show},getDataParams:function(t){var e=this.getData(),i=qL.superCall(this,"getDataParams",t),n=e.mapDimension("value"),o=e.getSum(n);return i.percent=o?+(e.get(n,t)/o*100).toFixed(2):0,i.$vars.push("percent"),i},defaultOption:{zlevel:0,z:2,legendHoverLink:!0,left:80,top:60,right:80,bottom:60,minSize:"0%",maxSize:"100%",sort:"descending",gap:0,funnelAlign:"center",label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:"solid"}},itemStyle:{borderColor:"#fff",borderWidth:1},emphasis:{label:{show:!0}}}})),KL=If.prototype,$L=["itemStyle","opacity"];KL.updateData=function(t,e,i){var n=this.childAt(0),o=t.hostModel,a=t.getItemModel(e),s=t.getItemLayout(e),l=t.getItemModel(e).get($L);l=null==l?1:l,n.useStyle({}),i?(n.setShape({points:s.points}),n.setStyle({opacity:0}),To(n,{style:{opacity:l}},o,e)):Io(n,{style:{opacity:l},shape:{points:s.points}},o,e);var u=a.getModel("itemStyle"),h=t.getItemVisual(e,"color");n.setStyle(r({lineJoin:"round",fill:h},u.getItemStyle(["opacity"]))),n.hoverStyle=u.getModel("emphasis").getItemStyle(),this._updateLabel(t,e),fo(this)},KL._updateLabel=function(t,e){var i=this.childAt(1),n=this.childAt(2),o=t.hostModel,a=t.getItemModel(e),r=t.getItemLayout(e).label,s=t.getItemVisual(e,"color");Io(i,{shape:{points:r.linePoints||r.linePoints}},o,e),Io(n,{style:{x:r.x,y:r.y}},o,e),n.attr({rotation:r.rotation,origin:[r.x,r.y],z2:10});var l=a.getModel("label"),u=a.getModel("emphasis.label"),h=a.getModel("labelLine"),c=a.getModel("emphasis.labelLine"),s=t.getItemVisual(e,"color");go(n.style,n.hoverStyle={},l,u,{labelFetcher:t.hostModel,labelDataIndex:e,defaultText:t.getName(e),autoColor:s,useInsideStyle:!!r.inside},{textAlign:r.textAlign,textVerticalAlign:r.verticalAlign}),n.ignore=n.normalIgnore=!l.get("show"),n.hoverIgnore=!u.get("show"),i.ignore=i.normalIgnore=!h.get("show"),i.hoverIgnore=!c.get("show"),i.setStyle({stroke:s}),i.setStyle(h.getModel("lineStyle").getLineStyle()),i.hoverStyle=c.getModel("lineStyle").getLineStyle()},u(If,tb);Ar.extend({type:"funnel",render:function(t,e,i){var n=t.getData(),o=this._data,a=this.group;n.diff(o).add(function(t){var e=new If(n,t);n.setItemGraphicEl(t,e),a.add(e)}).update(function(t,e){var i=o.getItemGraphicEl(e);i.updateData(n,t),a.add(i),n.setItemGraphicEl(t,i)}).remove(function(t){var e=o.getItemGraphicEl(t);a.remove(e)}).execute(),this._data=n},remove:function(){this.group.removeAll(),this._data=null},dispose:function(){}});Bs(uC("funnel")),zs(function(t,e,i){t.eachSeriesByType("funnel",function(t){var i=t.getData(),n=i.mapDimension("value"),o=t.get("sort"),a=Tf(t,e),r=Af(i,o),s=[Vo(t.get("minSize"),a.width),Vo(t.get("maxSize"),a.width)],l=i.getDataExtent(n),u=t.get("min"),h=t.get("max");null==u&&(u=Math.min(l[0],0)),null==h&&(h=l[1]);var c=t.get("funnelAlign"),d=t.get("gap"),f=(a.height-d*(i.count()-1))/i.count(),p=a.y,g=function(t,e){var o,r=Bo(i.get(n,t)||0,[u,h],s,!0);switch(c){case"left":o=a.x;break;case"center":o=a.x+(a.width-r)/2;break;case"right":o=a.x+a.width-r}return[[o,e],[o+r,e]]};"ascending"===o&&(f=-f,d=-d,p+=a.height,r=r.reverse());for(var m=0;ma&&(e[1-n]=e[n]+h.sign*a),e},tk=d,ek=Math.min,ik=Math.max,nk=Math.floor,ok=Math.ceil,ak=Go,rk=Math.PI;Nf.prototype={type:"parallel",constructor:Nf,_init:function(t,e,i){var n=t.dimensions,o=t.parallelAxisIndex;tk(n,function(t,i){var n=o[i],a=e.getComponent("parallelAxis",n),r=this._axesMap.set(t,new JL(t,Hl(a),[0,0],a.get("type"),n)),s="category"===r.type;r.onBand=s&&a.get("boundaryGap"),r.inverse=a.get("inverse"),a.axis=r,r.model=a,r.coordinateSystem=a.coordinateSystem=this},this)},update:function(t,e){this._updateAxesFromSeries(this._model,t)},containPoint:function(t){var e=this._makeLayoutInfo(),i=e.axisBase,n=e.layoutBase,o=e.pixelDimIndex,a=t[1-o],r=t[o];return a>=i&&a<=i+e.axisLength&&r>=n&&r<=n+e.layoutLength},getModel:function(){return this._model},_updateAxesFromSeries:function(t,e){e.eachSeries(function(i){if(t.contains(i,e)){var n=i.getData();tk(this.dimensions,function(t){var e=this._axesMap.get(t);e.scale.unionExtentFromData(n,n.mapDimension(t)),Wl(e.scale,e.model)},this)}},this)},resize:function(t,e){this._rect=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()}),this._layoutAxes()},getRect:function(){return this._rect},_makeLayoutInfo:function(){var t,e=this._model,i=this._rect,n=["x","y"],o=["width","height"],a=e.get("layout"),r="horizontal"===a?0:1,s=i[o[r]],l=[0,s],u=this.dimensions.length,h=Of(e.get("axisExpandWidth"),l),c=Of(e.get("axisExpandCount")||0,[0,u]),d=e.get("axisExpandable")&&u>3&&u>c&&c>1&&h>0&&s>0,f=e.get("axisExpandWindow");f?(t=Of(f[1]-f[0],l),f[1]=f[0]+t):(t=Of(h*(c-1),l),(f=[h*(e.get("axisExpandCenter")||nk(u/2))-t/2])[1]=f[0]+t);var p=(s-t)/(u-c);p<3&&(p=0);var g=[nk(ak(f[0]/h,1))+1,ok(ak(f[1]/h,1))-1],m=p/h*f[0];return{layout:a,pixelDimIndex:r,layoutBase:i[n[r]],layoutLength:s,axisBase:i[n[1-r]],axisLength:i[o[1-r]],axisExpandable:d,axisExpandWidth:h,axisCollapseWidth:p,axisExpandWindow:f,axisCount:u,winInnerIndices:g,axisExpandWindow0Pos:m}},_layoutAxes:function(){var t=this._rect,e=this._axesMap,i=this.dimensions,n=this._makeLayoutInfo(),o=n.layout;e.each(function(t){var e=[0,n.axisLength],i=t.inverse?1:0;t.setExtent(e[i],e[1-i])}),tk(i,function(e,i){var a=(n.axisExpandable?Rf:Ef)(i,n),r={horizontal:{x:a.position,y:n.axisLength},vertical:{x:0,y:a.position}},s={horizontal:rk/2,vertical:0},l=[r[o].x+t.x,r[o].y+t.y],u=s[o],h=xt();Mt(h,h,u),St(h,h,l),this._axesLayout[e]={position:l,rotation:u,transform:h,axisNameAvailableWidth:a.axisNameAvailableWidth,axisLabelShow:a.axisLabelShow,nameTruncateMaxWidth:a.nameTruncateMaxWidth,tickDirection:1,labelDirection:1}},this)},getAxis:function(t){return this._axesMap.get(t)},dataToPoint:function(t,e){return this.axisCoordToPoint(this._axesMap.get(e).dataToCoord(t),e)},eachActiveState:function(t,e,i,n){null==i&&(i=0),null==n&&(n=t.count());var o=this._axesMap,a=this.dimensions,r=[],s=[];d(a,function(e){r.push(t.mapDimension(e)),s.push(o.get(e).model)});for(var l=this.hasAxisBrushed(),u=i;uo*(1-h[0])?(l="jump",r=s-o*(1-h[2])):(r=s-o*h[1])>=0&&(r=s-o*(1-h[1]))<=0&&(r=0),(r*=e.axisExpandWidth/u)?QL(r,n,a,"all"):l="none";else{o=n[1]-n[0];(n=[ik(0,a[1]*s/o-o/2)])[1]=ek(a[1],n[0]+o),n[0]=n[1]-o}return{axisExpandWindow:n,behavior:l}}},Fa.register("parallel",{create:function(t,e){var i=[];return t.eachComponent("parallel",function(n,o){var a=new Nf(n,t,e);a.name="parallel_"+o,a.resize(n,e),n.coordinateSystem=a,a.model=n,i.push(a)}),t.eachSeries(function(e){if("parallel"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"parallel",index:e.get("parallelIndex"),id:e.get("parallelId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}});var sk=lI.extend({type:"baseParallelAxis",axis:null,activeIntervals:[],getAreaSelectStyle:function(){return Qb([["fill","color"],["lineWidth","borderWidth"],["stroke","borderColor"],["width","width"],["opacity","opacity"]])(this.getModel("areaSelectStyle"))},setActiveIntervals:function(t){var e=this.activeIntervals=i(t);if(e)for(var n=e.length-1;n>=0;n--)Fo(e[n])},getActiveState:function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(t))return"inactive";if(1===e.length){var i=e[0];if(i[0]<=t&&t<=i[1])return"active"}else for(var n=0,o=e.length;n5)return;var n=this._model.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]);"none"!==n.behavior&&this._dispatchExpand({axisExpandWindow:n.axisExpandWindow})}this._mouseDownPoint=null},mousemove:function(t){if(!this._mouseDownPoint&&Ip(this,"mousemove")){var e=this._model,i=e.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]),n=i.behavior;"jump"===n&&this._throttledDispatchExpand.debounceNextCall(e.get("axisExpandDebounce")),this._throttledDispatchExpand("none"===n?null:{axisExpandWindow:i.axisExpandWindow,animation:"jump"===n&&null})}}};Ns(function(t){Cf(t),Lf(t)}),YI.extend({type:"series.parallel",dependencies:["parallel"],visualColorAccessPath:"lineStyle.color",getInitialData:function(t,e){var i=this.getSource();return Tp(i,this),ml(i,this)},getRawIndicesByActiveState:function(t){var e=this.coordinateSystem,i=this.getData(),n=[];return e.eachActiveState(i,function(e,o){t===e&&n.push(i.getRawIndex(o))}),n},defaultOption:{zlevel:0,z:2,coordinateSystem:"parallel",parallelIndex:0,label:{show:!1},inactiveOpacity:.05,activeOpacity:1,lineStyle:{width:1,opacity:.45,type:"solid"},emphasis:{label:{show:!1}},progressive:500,smooth:!1,animationEasing:"linear"}});var Dk=.3,Ck=(Ar.extend({type:"parallel",init:function(){this._dataGroup=new tb,this.group.add(this._dataGroup),this._data,this._initialized},render:function(t,e,i,n){var o=this._dataGroup,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.dimensions,u=kp(t);if(a.diff(r).add(function(t){Pp(Lp(a,o,t,l,s),a,t,u)}).update(function(e,i){var o=r.getItemGraphicEl(i),h=Cp(a,e,l,s);a.setItemGraphicEl(e,o),Io(o,{shape:{points:h}},n&&!1===n.animation?null:t,e),Pp(o,a,e,u)}).remove(function(t){var e=r.getItemGraphicEl(t);o.remove(e)}).execute(),!this._initialized){this._initialized=!0;var h=Dp(s,t,function(){setTimeout(function(){o.removeClipPath()})});o.setClipPath(h)}this._data=a},incrementalPrepareRender:function(t,e,i){this._initialized=!0,this._data=null,this._dataGroup.removeAll()},incrementalRender:function(t,e,i){for(var n=e.getData(),o=e.coordinateSystem,a=o.dimensions,r=kp(e),s=t.start;sn&&(n=e)}),d(e,function(e){var o=new hL({type:"color",mappingMethod:"linear",dataExtent:[i,n],visual:t.get("color")}).mapValueToVisual(e.getLayout().value);e.setVisual("color",o);var a=e.getModel().get("itemStyle.color");null!=a&&e.setVisual("color",a)})}})});var Ok={_baseAxisDim:null,getInitialData:function(t,e){var i,n,o=e.getComponent("xAxis",this.get("xAxisIndex")),a=e.getComponent("yAxis",this.get("yAxisIndex")),r=o.get("type"),s=a.get("type");"category"===r?(t.layout="horizontal",i=o.getOrdinalMeta(),n=!0):"category"===s?(t.layout="vertical",i=a.getOrdinalMeta(),n=!0):t.layout=t.layout||"horizontal";var l=["x","y"],u="horizontal"===t.layout?0:1,h=this._baseAxisDim=l[u],c=l[1-u],f=[o,a],p=f[u].get("type"),g=f[1-u].get("type"),m=t.data;if(m&&n){var v=[];d(m,function(t,e){var i;t.value&&y(t.value)?(i=t.value.slice(),t.value.unshift(e)):y(t)?(i=t.slice(),t.unshift(e)):i=t,v.push(i)}),t.data=v}var x=this.defaultValueDimensions;return oC(this,{coordDimensions:[{name:h,type:qs(p),ordinalMeta:i,otherDims:{tooltip:!1,itemName:0},dimsDef:["base"]},{name:c,type:qs(g),dimsDef:x.slice()}],dimensionsCount:x.length+1})},getBaseAxis:function(){var t=this._baseAxisDim;return this.ecModel.getComponent(t+"Axis",this.get(t+"AxisIndex")).axis}};h(YI.extend({type:"series.boxplot",dependencies:["xAxis","yAxis","grid"],defaultValueDimensions:[{name:"min",defaultTooltip:!0},{name:"Q1",defaultTooltip:!0},{name:"median",defaultTooltip:!0},{name:"Q3",defaultTooltip:!0},{name:"max",defaultTooltip:!0}],dimensions:null,defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,layout:null,boxWidth:[7,50],itemStyle:{color:"#fff",borderWidth:1},emphasis:{itemStyle:{borderWidth:2,shadowBlur:5,shadowOffsetX:2,shadowOffsetY:2,shadowColor:"rgba(0,0,0,0.4)"}},animationEasing:"elasticOut",animationDuration:800}}),Ok,!0);var Ek=["itemStyle"],Rk=["emphasis","itemStyle"],zk=(Ar.extend({type:"boxplot",render:function(t,e,i){var n=t.getData(),o=this.group,a=this._data;this._data||o.removeAll();var r="horizontal"===t.get("layout")?1:0;n.diff(a).add(function(t){if(n.hasValue(t)){var e=ig(n.getItemLayout(t),n,t,r,!0);n.setItemGraphicEl(t,e),o.add(e)}}).update(function(t,e){var i=a.getItemGraphicEl(e);if(n.hasValue(t)){var s=n.getItemLayout(t);i?ng(s,i,n,t):i=ig(s,n,t,r),o.add(i),n.setItemGraphicEl(t,i)}else o.remove(i)}).remove(function(t){var e=a.getItemGraphicEl(t);e&&o.remove(e)}).execute(),this._data=n},remove:function(t){var e=this.group,i=this._data;this._data=null,i&&i.eachItemGraphicEl(function(t){t&&e.remove(t)})},dispose:B}),Pn.extend({type:"boxplotBoxPath",shape:{},buildPath:function(t,e){var i=e.points,n=0;for(t.moveTo(i[n][0],i[n][1]),n++;n<4;n++)t.lineTo(i[n][0],i[n][1]);for(t.closePath();n0?jk:Yk)}function n(t,e){return e.get(t>0?Uk:Xk)}var o=t.getData(),a=t.pipelineContext.large;if(o.setVisual({legendSymbol:"roundRect",colorP:i(1,t),colorN:i(-1,t),borderColorP:n(1,t),borderColorN:n(-1,t)}),!e.isSeriesFiltered(t))return!a&&{progress:function(t,e){for(var o;null!=(o=t.next());){var a=e.getItemModel(o),r=e.getItemLayout(o).sign;e.setItemVisual(o,{color:i(r,a),borderColor:n(r,a)})}}}}},Kk="undefined"!=typeof Float32Array?Float32Array:Array,$k={seriesType:"candlestick",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.getData(),n=pg(t,i),o=0,a=1,r=["x","y"],s=i.mapDimension(r[o]),l=i.mapDimension(r[a],!0),u=l[0],h=l[1],c=l[2],d=l[3];if(i.setLayout({candleWidth:n,isSimpleBox:n<=1.3}),!(null==s||l.length<4))return{progress:t.pipelineContext.large?function(t,i){for(var n,r,l=new Kk(5*t.count),f=0,p=[],g=[];null!=(r=t.next());){var m=i.get(s,r),v=i.get(u,r),y=i.get(h,r),x=i.get(c,r),_=i.get(d,r);isNaN(m)||isNaN(x)||isNaN(_)?(l[f++]=NaN,f+=4):(l[f++]=fg(i,r,v,y,h),p[o]=m,p[a]=x,n=e.dataToPoint(p,null,g),l[f++]=n?n[0]:NaN,l[f++]=n?n[1]:NaN,p[a]=_,n=e.dataToPoint(p,null,g),l[f++]=n?n[1]:NaN)}i.setLayout("largePoints",l)}:function(t,i){function r(t,i){var n=[];return n[o]=i,n[a]=t,isNaN(i)||isNaN(t)?[NaN,NaN]:e.dataToPoint(n)}function l(t,e,i){var a=e.slice(),r=e.slice();a[o]=Jn(a[o]+n/2,1,!1),r[o]=Jn(r[o]-n/2,1,!0),i?t.push(a,r):t.push(r,a)}function f(t){return t[o]=Jn(t[o],1),t}for(var p;null!=(p=t.next());){var g=i.get(s,p),m=i.get(u,p),v=i.get(h,p),y=i.get(c,p),x=i.get(d,p),_=Math.min(m,v),w=Math.max(m,v),b=r(_,g),S=r(w,g),M=r(y,g),I=r(x,g),T=[];l(T,S,0),l(T,b,1),T.push(f(I),f(S),f(M),f(b)),i.setItemLayout(p,{sign:fg(i,p,m,v,h),initBaseline:m>v?S[a]:b[a],ends:T,brushRect:function(t,e,i){var s=r(t,i),l=r(e,i);return s[o]-=n/2,l[o]-=n/2,{x:s[0],y:s[1],width:a?n:l[0]-s[0],height:a?l[1]-s[1]:n}}(y,x,g)})}}}}};Ns(function(t){t&&y(t.series)&&d(t.series,function(t){w(t)&&"k"===t.type&&(t.type="candlestick")})}),Bs(qk),zs($k),YI.extend({type:"series.effectScatter",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},brushSelector:"point",defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,effectType:"ripple",progressive:0,showEffectOn:"render",rippleEffect:{period:4,scale:2.5,brushType:"fill"},symbolSize:10}});var Jk=vg.prototype;Jk.stopEffectAnimation=function(){this.childAt(1).removeAll()},Jk.startEffectAnimation=function(t){for(var e=t.symbolType,i=t.color,n=this.childAt(1),o=0;o<3;o++){var a=Jl(e,-1,-1,2,2,i);a.attr({style:{strokeNoScale:!0},z2:99,silent:!0,scale:[.5,.5]});var r=-o/3*t.period+t.effectOffset;a.animate("",!0).when(t.period,{scale:[t.rippleScale/2,t.rippleScale/2]}).delay(r).start(),a.animateStyle(!0).when(t.period,{opacity:0}).delay(r).start(),n.add(a)}mg(n,t)},Jk.updateEffectAnimation=function(t){for(var e=this._effectCfg,i=this.childAt(1),n=["symbolType","period","rippleScale"],o=0;o "))},preventIncremental:function(){return!!this.get("effect.show")},getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,label:{show:!1,position:"end"},lineStyle:{opacity:.5}}}),iP=xg.prototype;iP.createLine=function(t,e,i){return new rf(t,e,i)},iP._updateEffectSymbol=function(t,e){var i=t.getItemModel(e).getModel("effect"),n=i.get("symbolSize"),o=i.get("symbol");y(n)||(n=[n,n]);var a=i.get("color")||t.getItemVisual(e,"color"),r=this.childAt(1);this._symbolType!==o&&(this.remove(r),(r=Jl(o,-.5,-.5,1,1,a)).z2=100,r.culling=!0,this.add(r)),r&&(r.setStyle("shadowColor",a),r.setStyle(i.getItemStyle(["color"])),r.attr("scale",n),r.setColor(a),r.attr("scale",n),this._symbolType=o,this._updateEffectAnimation(t,i,e))},iP._updateEffectAnimation=function(t,e,i){var n=this.childAt(1);if(n){var o=this,a=t.getItemLayout(i),r=1e3*e.get("period"),s=e.get("loop"),l=e.get("constantSpeed"),u=T(e.get("delay"),function(e){return e/t.count()*r/3}),h="function"==typeof u;if(n.ignore=!0,this.updateAnimationPoints(n,a),l>0&&(r=this.getLineLength(n)/l*1e3),r!==this._period||s!==this._loop){n.stopAnimation();var c=u;h&&(c=u(i)),n.__t>0&&(c=-r*n.__t),n.__t=0;var d=n.animate("",s).when(r,{__t:1}).delay(c).during(function(){o.updateSymbolPosition(n)});s||d.done(function(){o.remove(n)}),d.start()}this._period=r,this._loop=s}},iP.getLineLength=function(t){return uw(t.__p1,t.__cp1)+uw(t.__cp1,t.__p2)},iP.updateAnimationPoints=function(t,e){t.__p1=e[0],t.__p2=e[1],t.__cp1=e[2]||[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]},iP.updateData=function(t,e,i){this.childAt(0).updateData(t,e,i),this._updateEffectSymbol(t,e)},iP.updateSymbolPosition=function(t){var e=t.__p1,i=t.__p2,n=t.__cp1,o=t.__t,a=t.position,r=sn,s=ln;a[0]=r(e[0],n[0],i[0],o),a[1]=r(e[1],n[1],i[1],o);var l=s(e[0],n[0],i[0],o),u=s(e[1],n[1],i[1],o);t.rotation=-Math.atan2(u,l)-Math.PI/2,t.ignore=!1},iP.updateLayout=function(t,e){this.childAt(0).updateLayout(t,e);var i=t.getItemModel(e).getModel("effect");this._updateEffectAnimation(t,i,e)},u(xg,tb);var nP=_g.prototype;nP._createPolyline=function(t,e,i){var n=t.getItemLayout(e),o=new gM({shape:{points:n}});this.add(o),this._updateCommonStl(t,e,i)},nP.updateData=function(t,e,i){var n=t.hostModel;Io(this.childAt(0),{shape:{points:t.getItemLayout(e)}},n,e),this._updateCommonStl(t,e,i)},nP._updateCommonStl=function(t,e,i){var n=this.childAt(0),o=t.getItemModel(e),a=t.getItemVisual(e,"color"),s=i&&i.lineStyle,l=i&&i.hoverLineStyle;i&&!t.hasItemOption||(s=o.getModel("lineStyle").getLineStyle(),l=o.getModel("emphasis.lineStyle").getLineStyle()),n.useStyle(r({strokeNoScale:!0,fill:"none",stroke:a},s)),n.hoverStyle=l,fo(this)},nP.updateLayout=function(t,e){this.childAt(0).setShape("points",t.getItemLayout(e))},u(_g,tb);var oP=wg.prototype;oP.createLine=function(t,e,i){return new _g(t,e,i)},oP.updateAnimationPoints=function(t,e){this._points=e;for(var i=[0],n=0,o=1;o=0&&!(n[r]<=e);r--);r=Math.min(r,o-2)}else{for(var r=a;re);r++);r=Math.min(r-1,o-2)}J(t.position,i[r],i[r+1],(e-n[r])/(n[r+1]-n[r]));var s=i[r+1][0]-i[r][0],l=i[r+1][1]-i[r][1];t.rotation=-Math.atan2(l,s)-Math.PI/2,this._lastFrame=r,this._lastFramePercent=e,t.ignore=!1}},u(wg,xg);var aP=Un({shape:{polyline:!1,curveness:0,segs:[]},buildPath:function(t,e){var i=e.segs,n=e.curveness;if(e.polyline)for(r=0;r0){t.moveTo(i[r++],i[r++]);for(var a=1;a0){var c=(s+u)/2-(l-h)*n,d=(l+h)/2-(u-s)*n;t.quadraticCurveTo(c,d,u,h)}else t.lineTo(u,h)}},findDataIndex:function(t,e){var i=this.shape,n=i.segs,o=i.curveness;if(i.polyline)for(var a=0,r=0;r0)for(var l=n[r++],u=n[r++],h=1;h0){if(_n(l,u,(l+c)/2-(u-d)*o,(u+d)/2-(c-l)*o,c,d))return a}else if(yn(l,u,c,d))return a;a++}return-1}}),rP=bg.prototype;rP.isPersistent=function(){return!this._incremental},rP.updateData=function(t){this.group.removeAll();var e=new aP({rectHover:!0,cursor:"default"});e.setShape({segs:t.getLayout("linesPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},rP.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>5e5?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},rP.incrementalUpdate=function(t,e){var i=new aP;i.setShape({segs:e.getLayout("linesPoints")}),this._setCommon(i,e,!!this._incremental),this._incremental?this._incremental.addDisplayable(i,!0):(i.rectHover=!0,i.cursor="default",i.__startIndex=t.start,this.group.add(i))},rP.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},rP._setCommon=function(t,e,i){var n=e.hostModel;t.setShape({polyline:n.get("polyline"),curveness:n.get("lineStyle.curveness")}),t.useStyle(n.getModel("lineStyle").getLineStyle()),t.style.strokeNoScale=!0;var o=e.getVisual("color");o&&t.setStyle("stroke",o),t.setStyle("fill"),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>0&&(t.dataIndex=i+t.__startIndex)}))},rP._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()};var sP={seriesType:"lines",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.get("polyline"),n=t.pipelineContext.large;return{progress:function(o,a){var r=[];if(n){var s,l=o.end-o.start;if(i){for(var u=0,h=o.start;h0){var I=a(v)?s:l;v>0&&(v=v*S+b),x[_++]=I[M],x[_++]=I[M+1],x[_++]=I[M+2],x[_++]=I[M+3]*v*256}else _+=4}return c.putImageData(y,0,0),h},_getBrush:function(){var t=this._brushCanvas||(this._brushCanvas=iw()),e=this.pointSize+this.blurSize,i=2*e;t.width=i,t.height=i;var n=t.getContext("2d");return n.clearRect(0,0,i,i),n.shadowOffsetX=i,n.shadowBlur=this.blurSize,n.shadowColor="#000",n.beginPath(),n.arc(-e,e,this.pointSize,0,2*Math.PI,!0),n.closePath(),n.fill(),t},_getGradient:function(t,e,i){for(var n=this._gradientPixels,o=n[i]||(n[i]=new Uint8ClampedArray(1024)),a=[0,0,0,0],r=0,s=0;s<256;s++)e[i](s/255,!0,a),o[r++]=a[0],o[r++]=a[1],o[r++]=a[2],o[r++]=a[3];return o}},Zs({type:"heatmap",render:function(t,e,i){var n;e.eachComponent("visualMap",function(e){e.eachTargetSeries(function(i){i===t&&(n=e)})}),this.group.removeAll(),this._incrementalDisplayable=null;var o=t.coordinateSystem;"cartesian2d"===o.type||"calendar"===o.type?this._renderOnCartesianAndCalendar(t,i,0,t.getData().count()):Ag(o)&&this._renderOnGeo(o,t,n,i)},incrementalPrepareRender:function(t,e,i){this.group.removeAll()},incrementalRender:function(t,e,i,n){e.coordinateSystem&&this._renderOnCartesianAndCalendar(e,n,t.start,t.end,!0)},_renderOnCartesianAndCalendar:function(t,e,i,n,o){var r,s,l=t.coordinateSystem;if("cartesian2d"===l.type){var u=l.getAxis("x"),h=l.getAxis("y");r=u.getBandWidth(),s=h.getBandWidth()}for(var c=this.group,d=t.getData(),f=t.getModel("itemStyle").getItemStyle(["color"]),p=t.getModel("emphasis.itemStyle").getItemStyle(),g=t.getModel("label"),m=t.getModel("emphasis.label"),v=l.type,y="cartesian2d"===v?[d.mapDimension("x"),d.mapDimension("y"),d.mapDimension("value")]:[d.mapDimension("time"),d.mapDimension("value")],x=i;x=e.y&&t[1]<=e.y+e.height:i.contain(i.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},pointToData:function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},dataToPoint:function(t){var e=this.getAxis(),i=this.getRect(),n=[],o="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=e.toGlobalCoord(e.dataToCoord(+t)),n[1-o]=0===o?i.y+i.height/2:i.x+i.width/2,n}},Fa.register("single",{create:function(t,e){var i=[];return t.eachComponent("singleAxis",function(n,o){var a=new $g(n,t,e);a.name="single_"+o,a.resize(n,e),n.coordinateSystem=a,i.push(a)}),t.eachSeries(function(e){if("singleAxis"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"singleAxis",index:e.get("singleAxisIndex"),id:e.get("singleAxisId")})[0];e.coordinateSystem=i&&i.coordinateSystem}}),i},dimensions:$g.prototype.dimensions});var gP=["axisLine","axisTickLabel","axisName"],mP=XD.extend({type:"singleAxis",axisPointerClass:"SingleAxisPointer",render:function(t,e,i,n){var o=this.group;o.removeAll();var a=Jg(t),r=new FD(t,a);d(gP,r.add,r),o.add(r.getGroup()),t.get("splitLine.show")&&this._splitLine(t),mP.superCall(this,"render",t,e,i,n)},_splitLine:function(t){var e=t.axis;if(!e.scale.isBlank()){var i=t.getModel("splitLine"),n=i.getModel("lineStyle"),o=n.get("width"),a=n.get("color");a=a instanceof Array?a:[a];for(var r=t.coordinateSystem.getRect(),s=e.isHorizontal(),l=[],u=0,h=e.getTicksCoords({tickModel:i}),c=[],d=[],f=0;f=0)&&i({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})})},remove:function(t,e){gm(e.getZr(),"axisPointer"),IP.superApply(this._model,"remove",arguments)},dispose:function(t,e){gm("axisPointer",e),IP.superApply(this._model,"dispose",arguments)}}),TP=Bi(),AP=i,DP=m;(mm.prototype={_group:null,_lastGraphicKey:null,_handle:null,_dragging:!1,_lastValue:null,_lastStatus:null,_payloadInfo:null,animationThreshold:15,render:function(t,e,i,n){var o=e.get("value"),a=e.get("status");if(this._axisModel=t,this._axisPointerModel=e,this._api=i,n||this._lastValue!==o||this._lastStatus!==a){this._lastValue=o,this._lastStatus=a;var r=this._group,s=this._handle;if(!a||"hide"===a)return r&&r.hide(),void(s&&s.hide());r&&r.show(),s&&s.show();var l={};this.makeElOption(l,o,t,e,i);var u=l.graphicKey;u!==this._lastGraphicKey&&this.clear(i),this._lastGraphicKey=u;var h=this._moveAnimation=this.determineAnimation(t,e);if(r){var c=v(vm,e,h);this.updatePointerEl(r,l,c,e),this.updateLabelEl(r,l,c,e)}else r=this._group=new tb,this.createPointerEl(r,l,t,e),this.createLabelEl(r,l,t,e),i.getZr().add(r);wm(r,e,!0),this._renderHandle(o)}},remove:function(t){this.clear(t)},dispose:function(t){this.clear(t)},determineAnimation:function(t,e){var i=e.get("animation"),n=t.axis,o="category"===n.type,a=e.get("snap");if(!a&&!o)return!1;if("auto"===i||null==i){var r=this.animationThreshold;if(o&&n.getBandWidth()>r)return!0;if(a){var s=Mh(t).seriesDataCount,l=n.getExtent();return Math.abs(l[0]-l[1])/s>r}return!1}return!0===i},makeElOption:function(t,e,i,n,o){},createPointerEl:function(t,e,i,n){var o=e.pointer;if(o){var a=TP(t).pointerEl=new zM[o.type](AP(e.pointer));t.add(a)}},createLabelEl:function(t,e,i,n){if(e.label){var o=TP(t).labelEl=new yM(AP(e.label));t.add(o),xm(o,n)}},updatePointerEl:function(t,e,i){var n=TP(t).pointerEl;n&&(n.setStyle(e.pointer.style),i(n,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,i,n){var o=TP(t).labelEl;o&&(o.setStyle(e.label.style),i(o,{shape:e.label.shape,position:e.label.position}),xm(o,n))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e=this._axisPointerModel,i=this._api.getZr(),n=this._handle,o=e.getModel("handle"),a=e.get("status");if(!o.get("show")||!a||"hide"===a)return n&&i.remove(n),void(this._handle=null);var r;this._handle||(r=!0,n=this._handle=Po(o.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){mw(t.event)},onmousedown:DP(this._onHandleDragMove,this,0,0),drift:DP(this._onHandleDragMove,this),ondragend:DP(this._onHandleDragEnd,this)}),i.add(n)),wm(n,e,!1);var s=["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"];n.setStyle(o.getItemStyle(null,s));var l=o.get("size");y(l)||(l=[l,l]),n.attr("scale",[l[0]/2,l[1]/2]),Nr(this,"_doDispatchAxisPointer",o.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,r)}},_moveHandleToValue:function(t,e){vm(this._axisPointerModel,!e&&this._moveAnimation,this._handle,_m(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var i=this._handle;if(i){this._dragging=!0;var n=this.updateHandleTransform(_m(i),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=n,i.stopAnimation(),i.attr(_m(n)),TP(i).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),i=this._group,n=this._handle;e&&i&&(this._lastGraphicKey=null,i&&e.remove(i),n&&e.remove(n),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}}).constructor=mm,ji(mm);var CP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.grid,s=n.get("type"),l=km(r,a).getOtherAxis(a).getGlobalExtent(),u=a.toGlobalCoord(a.dataToCoord(e,!0));if(s&&"none"!==s){var h=bm(n),c=LP[s](a,u,l,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Lh(r.model,i),i,n,o)},getHandleTransform:function(t,e,i){var n=Lh(e.axis.grid.model,e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.grid,r=o.getGlobalExtent(!0),s=km(a,o).getOtherAxis(o).getGlobalExtent(),l="x"===o.dim?0:1,u=t.position;u[l]+=e[l],u[l]=Math.min(r[1],u[l]),u[l]=Math.max(r[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];var d=[{verticalAlign:"middle"},{align:"center"}];return{position:u,rotation:t.rotation,cursorPoint:c,tooltipOption:d[l]}}}),LP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Pm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=Math.max(1,t.getBandWidth()),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Pm(t))}}};XD.registerAxisPointerClass("CartesianAxisPointer",CP),Ns(function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!y(e)&&(t.axisPointer.link=[e])}}),Os(VT.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=vh(t,e)}),Es({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,i){var n=t.currTrigger,o=[t.x,t.y],a=t,r=t.dispatchAction||m(i.dispatchAction,i),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){lm(o)&&(o=xP({seriesIndex:a.seriesIndex,dataIndex:a.dataIndex},e).point);var l=lm(o),u=a.axesInfo,h=s.axesInfo,c="leave"===n||lm(o),d={},f={},p={list:[],map:{}},g={showPointer:wP(em,f),showTooltip:wP(im,p)};_P(s.coordSysMap,function(t,e){var i=l||t.containPoint(o);_P(s.coordSysAxesInfo[e],function(t,e){var n=t.axis,a=rm(u,t);if(!c&&i&&(!u||a)){var r=a&&a.value;null!=r||l||(r=n.pointToData(o)),null!=r&&Qg(t,r,g,!1,d)}})});var v={};return _P(h,function(t,e){var i=t.linkGroup;i&&!f[e]&&_P(i.axesInfo,function(e,n){var o=f[n];if(e!==t&&o){var a=o.value;i.mapper&&(a=t.axis.scale.parse(i.mapper(a,sm(e),sm(t)))),v[t.key]=a}})}),_P(v,function(t,e){Qg(h[e],t,g,!0,d)}),nm(f,h,d),om(p,o,t,r),am(h,0,i),d}});var kP=["x","y"],PP=["width","height"],NP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.coordinateSystem,s=Om(r,1-Nm(a)),l=r.dataToPoint(e)[0],u=n.get("type");if(u&&"none"!==u){var h=bm(n),c=OP[u](a,l,s,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Jg(i),i,n,o)},getHandleTransform:function(t,e,i){var n=Jg(e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.coordinateSystem,r=Nm(o),s=Om(a,r),l=t.position;l[r]+=e[r],l[r]=Math.min(s[1],l[r]),l[r]=Math.max(s[0],l[r]);var u=Om(a,1-r),h=(u[1]+u[0])/2,c=[h,h];return c[r]=l[r],{position:l,rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}}}),OP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Nm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=t.getBandWidth(),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Nm(t))}}};XD.registerAxisPointerClass("SingleAxisPointer",NP),Ws({type:"single"});var EP=YI.extend({type:"series.themeRiver",dependencies:["singleAxis"],nameMap:null,init:function(t){EP.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()}},fixData:function(t){var e=t.length,i=[];Zi(t,function(t){return t[2]}).buckets.each(function(t,e){i.push({name:e,dataList:t})});for(var n=i.length,o=-1,a=-1,r=0;ro&&(o=s,a=r)}for(var l=0;lMath.PI/2?"right":"left"):x&&"center"!==x?"left"===x?(f=u.r0+y,p>Math.PI/2&&(x="right")):"right"===x&&(f=u.r-y,p>Math.PI/2&&(x="left")):(f=(u.r+u.r0)/2,x="center"),d.attr("style",{text:l,textAlign:x,textVerticalAlign:n("verticalAlign")||"middle",opacity:n("opacity")});var _=f*g+u.cx,w=f*m+u.cy;d.attr("position",[_,w]);var b=n("rotate"),S=0;"radial"===b?(S=-p)<-Math.PI/2&&(S+=Math.PI):"tangential"===b?(S=Math.PI/2-p)>Math.PI/2?S-=Math.PI:S<-Math.PI/2&&(S+=Math.PI):"number"==typeof b&&(S=b*Math.PI/180),d.attr("rotation",S)},VP._initEvents=function(t,e,i,n){t.off("mouseover").off("mouseout").off("emphasis").off("normal");var o=this,a=function(){o.onEmphasis(n)},r=function(){o.onNormal()};i.isAnimationEnabled()&&t.on("mouseover",a).on("mouseout",r).on("emphasis",a).on("normal",r).on("downplay",function(){o.onDownplay()}).on("highlight",function(){o.onHighlight()})},u(Vm,tb);Ar.extend({type:"sunburst",init:function(){},render:function(t,e,i,n){function o(i,n){if(c||!i||i.getValue()||(i=null),i!==l&&n!==l)if(n&&n.piece)i?(n.piece.updateData(!1,i,"normal",t,e),s.setItemGraphicEl(i.dataIndex,n.piece)):a(n);else if(i){var o=new Vm(i,t,e);h.add(o),s.setItemGraphicEl(i.dataIndex,o)}}function a(t){t&&t.piece&&(h.remove(t.piece),t.piece=null)}var r=this;this.seriesModel=t,this.api=i,this.ecModel=e;var s=t.getData(),l=s.tree.root,u=t.getViewRoot(),h=this.group,c=t.get("renderLabelForZeroData"),d=[];u.eachNode(function(t){d.push(t)});var f=this._oldChildren||[];if(function(t,e){function i(t){return t.getId()}function n(i,n){o(null==i?null:t[i],null==n?null:e[n])}0===t.length&&0===e.length||new Xs(e,t,i,i).add(n).update(n).remove(v(n,null)).execute()}(d,f),function(i,n){if(n.depth>0){r.virtualPiece?r.virtualPiece.updateData(!1,i,"normal",t,e):(r.virtualPiece=new Vm(i,t,e),h.add(r.virtualPiece)),n.piece._onclickEvent&&n.piece.off("click",n.piece._onclickEvent);var o=function(t){r._rootToNode(n.parentNode)};n.piece._onclickEvent=o,r.virtualPiece.on("click",o)}else r.virtualPiece&&(h.remove(r.virtualPiece),r.virtualPiece=null)}(l,u),n&&n.highlight&&n.highlight.piece){var p=t.getShallow("highlightPolicy");n.highlight.piece.onEmphasis(p)}else if(n&&n.unhighlight){var g=this.virtualPiece;!g&&l.children.length&&(g=l.children[0].piece),g&&g.onNormal()}this._initEvents(),this._oldChildren=d},dispose:function(){},_initEvents:function(){var t=this,e=function(e){var i=!1;t.seriesModel.getViewRoot().eachNode(function(n){if(!i&&n.piece&&n.piece.childAt(0)===e.target){var o=n.getModel().get("nodeClick");if("rootToNode"===o)t._rootToNode(n);else if("link"===o){var a=n.getModel(),r=a.get("link");if(r){var s=a.get("target",!0)||"_blank";window.open(r,s)}}i=!0}})};this.group._onclickEvent&&this.group.off("click",this.group._onclickEvent),this.group.on("click",e),this.group._onclickEvent=e},_rootToNode:function(t){t!==this.seriesModel.getViewRoot()&&this.api.dispatchAction({type:"sunburstRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t})},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var GP="sunburstRootToNode";Es({type:GP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[GP],e);if(n){var o=e.getViewRoot();o&&(t.direction=hd(o,n.node)?"rollUp":"drillDown"),e.resetViewRoot(n.node)}})});var FP="sunburstHighlight";Es({type:FP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[FP],e);n&&(t.highlight=n.node)})});Es({type:"sunburstUnhighlight",update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){t.unhighlight=!0})});var WP=Math.PI/180;Bs(v(uC,"sunburst")),zs(v(function(t,e,i,n){e.eachSeriesByType(t,function(t){var e=t.get("center"),n=t.get("radius");y(n)||(n=[0,n]),y(e)||(e=[e,e]);var o=i.getWidth(),a=i.getHeight(),r=Math.min(o,a),s=Vo(e[0],o),l=Vo(e[1],a),u=Vo(n[0],r/2),h=Vo(n[1],r/2),c=-t.get("startAngle")*WP,f=t.get("minAngle")*WP,p=t.getData().tree.root,g=t.getViewRoot(),m=g.depth,v=t.get("sort");null!=v&&Zm(g,v);var x=0;d(g.children,function(t){!isNaN(t.getValue())&&x++});var _=g.getValue(),w=Math.PI/(_||x)*2,b=g.depth>0,S=g.height-(b?-1:1),M=(h-u)/(S||1),I=t.get("clockwise"),T=t.get("stillShowZeroSum"),A=I?1:-1,D=function(t,e){if(t){var i=e;if(t!==p){var n=t.getValue(),o=0===_&&T?w:n*w;on[1]&&n.reverse(),{coordSys:{type:"polar",cx:t.cx,cy:t.cy,r:n[1],r0:n[0]},api:{coord:m(function(n){var o=e.dataToRadius(n[0]),a=i.dataToAngle(n[1]),r=t.coordToPoint([o,a]);return r.push(o,a*Math.PI/180),r}),size:m(qm,t)}}},calendar:function(t){var e=t.getRect(),i=t.getRangeInfo();return{coordSys:{type:"calendar",x:e.x,y:e.y,width:e.width,height:e.height,cellWidth:t.getCellWidth(),cellHeight:t.getCellHeight(),rangeInfo:{start:i.start,end:i.end,weeks:i.weeks,dayCount:i.allDay}},api:{coord:function(e,i){return t.dataToPoint(e,i)}}}}};YI.extend({type:"series.custom",dependencies:["grid","polar","geo","singleAxis","calendar"],defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,useTransform:!0},getInitialData:function(t,e){return ml(this.getSource(),this)},getDataParams:function(t,e,i){var n=YI.prototype.getDataParams.apply(this,arguments);return i&&(n.info=i.info),n}}),Ar.extend({type:"custom",_data:null,render:function(t,e,i,n){var o=this._data,a=t.getData(),r=this.group,s=Qm(t,a,e,i);a.diff(o).add(function(e){ev(null,e,s(e,n),t,r,a)}).update(function(e,i){ev(o.getItemGraphicEl(i),e,s(e,n),t,r,a)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&r.remove(e)}).execute(),this._data=a},incrementalPrepareRender:function(t,e,i){this.group.removeAll(),this._data=null},incrementalRender:function(t,e,i,n,o){for(var a=e.getData(),r=Qm(e,a,i,n),s=t.start;s=0;l--)null==o[l]?o.splice(l,1):delete o[l].$action},_flatten:function(t,e,i){d(t,function(t){if(t){i&&(t.parentOption=i),e.push(t);var n=t.children;"group"===t.type&&n&&this._flatten(n,e,t),delete t.children}},this)},useElOptionsToUpdate:function(){var t=this._elOptionsToUpdate;return this._elOptionsToUpdate=null,t}});Ws({type:"graphic",init:function(t,e){this._elMap=R(),this._lastGraphicModel},render:function(t,e,i){t!==this._lastGraphicModel&&this._clear(),this._lastGraphicModel=t,this._updateElements(t),this._relocate(t,i)},_updateElements:function(t){var e=t.useElOptionsToUpdate();if(e){var i=this._elMap,n=this.group;d(e,function(e){var o=e.$action,a=e.id,r=i.get(a),s=e.parentId,l=null!=s?i.get(s):n,u=e.style;"text"===e.type&&u&&(e.hv&&e.hv[1]&&(u.textVerticalAlign=u.textBaseline=null),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke));var h=fv(e);o&&"merge"!==o?"replace"===o?(dv(r,i),cv(a,l,h,i)):"remove"===o&&dv(r,i):r?r.attr(h):cv(a,l,h,i);var c=i.get(a);c&&(c.__ecGraphicWidth=e.width,c.__ecGraphicHeight=e.height,yv(c,t))})}},_relocate:function(t,e){for(var i=t.option.elements,n=this.group,o=this._elMap,a=i.length-1;a>=0;a--){var r=i[a],s=o.get(r.id);if(s){var l=s.parent;da(s,r,l===n?{width:e.getWidth(),height:e.getHeight()}:{width:l.__ecGraphicWidth||0,height:l.__ecGraphicHeight||0},null,{hv:r.hv,boundingMode:r.bounding})}}},_clear:function(){var t=this._elMap;t.each(function(e){dv(e,t)}),this._elMap=R()},dispose:function(){this._clear()}});var KP=Fs({type:"legend.plain",dependencies:["series"],layoutMode:{type:"box",ignoreSize:!0},init:function(t,e,i){this.mergeDefaultAndTheme(t,i),t.selected=t.selected||{}},mergeOption:function(t){KP.superCall(this,"mergeOption",t)},optionUpdated:function(){this._updateData(this.ecModel);var t=this._data;if(t[0]&&"single"===this.get("selectedMode")){for(var e=!1,i=0;i=0},defaultOption:{zlevel:0,z:4,show:!0,orient:"horizontal",left:"center",top:0,align:"auto",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemGap:10,itemWidth:25,itemHeight:14,inactiveColor:"#ccc",textStyle:{color:"#333"},selectedMode:!0,tooltip:{show:!1}}});Es("legendToggleSelect","legendselectchanged",v(xv,"toggleSelected")),Es("legendSelect","legendselected",v(xv,"select")),Es("legendUnSelect","legendunselected",v(xv,"unSelect"));var $P=v,JP=d,QP=tb,tN=Ws({type:"legend.plain",newlineDisabled:!1,init:function(){this.group.add(this._contentGroup=new QP),this._backgroundEl,this._isFirstRender=!0},getContentGroup:function(){return this._contentGroup},render:function(t,e,i){var n=this._isFirstRender;if(this._isFirstRender=!1,this.resetInner(),t.get("show",!0)){var o=t.get("align");o&&"auto"!==o||(o="right"===t.get("left")&&"vertical"===t.get("orient")?"right":"left"),this.renderInner(o,t,e,i);var a=t.getBoxLayoutParams(),s={width:i.getWidth(),height:i.getHeight()},l=t.get("padding"),u=ca(a,s,l),h=this.layoutInner(t,o,u,n),c=ca(r({width:h.width,height:h.height},a),s,l);this.group.attr("position",[c.x-h.x,c.y-h.y]),this.group.add(this._backgroundEl=wv(h,t))}},resetInner:function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl)},renderInner:function(t,e,i,n){var o=this.getContentGroup(),a=R(),r=e.get("selectedMode"),s=[];i.eachRawSeries(function(t){!t.get("legendHoverLink")&&s.push(t.id)}),JP(e.getData(),function(l,u){var h=l.get("name");if(this.newlineDisabled||""!==h&&"\n"!==h){var c=i.getSeriesByName(h)[0];if(!a.get(h))if(c){var d=c.getData(),f=d.getVisual("color");"function"==typeof f&&(f=f(c.getDataParams(0)));var p=d.getVisual("legendSymbol")||"roundRect",g=d.getVisual("symbol");this._createItem(h,u,l,e,p,g,t,f,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,c.name,null,n,s)).on("mouseout",$P(Mv,c.name,null,n,s)),a.set(h,!0)}else i.eachRawSeries(function(i){if(!a.get(h)&&i.legendDataProvider){var o=i.legendDataProvider(),c=o.indexOfName(h);if(c<0)return;var d=o.getItemVisual(c,"color");this._createItem(h,u,l,e,"roundRect",null,t,d,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,null,h,n,s)).on("mouseout",$P(Mv,null,h,n,s)),a.set(h,!0)}},this)}else o.add(new QP({newline:!0}))},this)},_createItem:function(t,e,i,n,o,r,s,l,u){var h=n.get("itemWidth"),c=n.get("itemHeight"),d=n.get("inactiveColor"),f=n.get("symbolKeepAspect"),p=n.isSelected(t),g=new QP,m=i.getModel("textStyle"),v=i.get("icon"),y=i.getModel("tooltip"),x=y.parentModel;if(o=v||o,g.add(Jl(o,0,0,h,c,p?l:d,null==f||f)),!v&&r&&(r!==o||"none"===r)){var _=.8*c;"none"===r&&(r="circle"),g.add(Jl(r,(h-_)/2,(c-_)/2,_,_,p?l:d,null==f||f))}var w="left"===s?h+5:-5,b=s,S=n.get("formatter"),M=t;"string"==typeof S&&S?M=S.replace("{name}",null!=t?t:""):"function"==typeof S&&(M=S(t)),g.add(new rM({style:mo({},m,{text:M,x:w,y:c/2,textFill:p?m.getTextColor():d,textAlign:b,textVerticalAlign:"middle"})}));var I=new yM({shape:g.getBoundingRect(),invisible:!0,tooltip:y.get("show")?a({content:t,formatter:x.get("formatter",!0)||function(){return t},formatterParams:{componentType:"legend",legendIndex:n.componentIndex,name:t,$vars:["name"]}},y.option):null});return g.add(I),g.eachChild(function(t){t.silent=!0}),I.silent=!u,this.getContentGroup().add(g),fo(g),g.__legendDataIndex=e,g},layoutInner:function(t,e,i){var n=this.getContentGroup();aI(t.get("orient"),n,t.get("itemGap"),i.width,i.height);var o=n.getBoundingRect();return n.attr("position",[-o.x,-o.y]),this.group.getBoundingRect()},remove:function(){this.getContentGroup().removeAll(),this._isFirstRender=!0}});Os(function(t){var e=t.findComponents({mainType:"legend"});e&&e.length&&t.filterSeries(function(t){for(var i=0;ii[l],p=[-c.x,-c.y];n||(p[s]=o.position[s]);var g=[0,0],m=[-d.x,-d.y],v=A(t.get("pageButtonGap",!0),t.get("itemGap",!0));f&&("end"===t.get("pageButtonPosition",!0)?m[s]+=i[l]-d[l]:g[s]+=d[l]+v),m[1-s]+=c[u]/2-d[u]/2,o.attr("position",p),a.attr("position",g),r.attr("position",m);var y=this.group.getBoundingRect();if((y={x:0,y:0})[l]=f?i[l]:c[l],y[u]=Math.max(c[u],d[u]),y[h]=Math.min(0,d[h]+m[1-s]),a.__rectSize=i[l],f){var x={x:0,y:0};x[l]=Math.max(i[l]-d[l]-v,0),x[u]=y[u],a.setClipPath(new yM({shape:x})),a.__rectSize=x[l]}else r.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var _=this._getPageInfo(t);return null!=_.pageIndex&&Io(o,{position:_.contentPosition},!!f&&t),this._updatePageInfoView(t,_),y},_pageGo:function(t,e,i){var n=this._getPageInfo(e)[t];null!=n&&i.dispatchAction({type:"legendScroll",scrollDataIndex:n,legendId:e.id})},_updatePageInfoView:function(t,e){var i=this._controllerGroup;d(["pagePrev","pageNext"],function(n){var o=null!=e[n+"DataIndex"],a=i.childOfName(n);a&&(a.setStyle("fill",o?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),a.cursor=o?"pointer":"default")});var n=i.childOfName("pageText"),o=t.get("pageFormatter"),a=e.pageIndex,r=null!=a?a+1:0,s=e.pageCount;n&&o&&n.setStyle("text",_(o)?o.replace("{current}",r).replace("{total}",s):o({current:r,total:s}))},_getPageInfo:function(t){function e(t){if(t){var e=t.getBoundingRect(),i=e[l]+t.position[r];return{s:i,e:i+e[s],i:t.__legendDataIndex}}}function i(t,e){return t.e>=e&&t.s<=e+a}var n=t.get("scrollDataIndex",!0),o=this.getContentGroup(),a=this._containerGroup.__rectSize,r=t.getOrient().index,s=nN[r],l=oN[r],u=this._findTargetItemIndex(n),h=o.children(),c=h[u],d=h.length,f=d?1:0,p={contentPosition:o.position.slice(),pageCount:f,pageIndex:f-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!c)return p;var g=e(c);p.contentPosition[r]=-g.s;for(var m=u+1,v=g,y=g,x=null;m<=d;++m)(!(x=e(h[m]))&&y.e>v.s+a||x&&!i(x,v.s))&&(v=y.i>v.i?y:x)&&(null==p.pageNextDataIndex&&(p.pageNextDataIndex=v.i),++p.pageCount),y=x;for(var m=u-1,v=g,y=g,x=null;m>=-1;--m)(x=e(h[m]))&&i(y,x.s)||!(v.i=0;){var r=o.indexOf("|}"),s=o.substr(a+"{marker".length,r-a-"{marker".length);s.indexOf("sub")>-1?n["marker"+s]={textWidth:4,textHeight:4,textBorderRadius:2,textBackgroundColor:e[s],textOffset:[3,0]}:n["marker"+s]={textWidth:10,textHeight:10,textBorderRadius:5,textBackgroundColor:e[s]},a=(o=o.substr(r+1)).indexOf("{marker")}this.el=new rM({style:{rich:n,text:t,textLineHeight:20,textBackgroundColor:i.get("backgroundColor"),textBorderRadius:i.get("borderRadius"),textFill:i.get("textStyle.color"),textPadding:i.get("padding")},z:i.get("z")}),this._zr.add(this.el);var l=this;this.el.on("mouseover",function(){l._enterable&&(clearTimeout(l._hideTimeout),l._show=!0),l._inContent=!0}),this.el.on("mouseout",function(){l._enterable&&l._show&&l.hideLater(l._hideDelay),l._inContent=!1})},setEnterable:function(t){this._enterable=t},getSize:function(){var t=this.el.getBoundingRect();return[t.width,t.height]},moveTo:function(t,e){this.el&&this.el.attr("position",[t,e])},hide:function(){this.el?this.el.hide():true,this._show=!1},hideLater:function(t){!this._show||this._inContent&&this._enterable||(t?(this._hideDelay=t,this._show=!1,this._hideTimeout=setTimeout(m(this.hide,this),t)):this.hide())},isShow:function(){return this._show},getOuterSize:function(){return this.getSize()}};var uN=m,hN=d,cN=Vo,dN=new yM({shape:{x:-1,y:-1,width:2,height:2}});Ws({type:"tooltip",init:function(t,e){if(!U_.node){var i=t.getComponent("tooltip").get("renderMode");this._renderMode=Hi(i);var n;"html"===this._renderMode?(n=new Cv(e.getDom(),e),this._newLine="
"):(n=new Lv(e),this._newLine="\n"),this._tooltipContent=n}},render:function(t,e,i){if(!U_.node){this.group.removeAll(),this._tooltipModel=t,this._ecModel=e,this._api=i,this._lastDataByCoordSys=null,this._alwaysShowContent=t.get("alwaysShowContent");var n=this._tooltipContent;n.update(),n.setEnterable(t.get("enterable")),this._initGlobalListener(),this._keepShow()}},_initGlobalListener:function(){var t=this._tooltipModel.get("triggerOn");um("itemTooltip",this._api,uN(function(e,i,n){"none"!==t&&(t.indexOf(e)>=0?this._tryShow(i,n):"leave"===e&&this._hide(n))},this))},_keepShow:function(){var t=this._tooltipModel,e=this._ecModel,i=this._api;if(null!=this._lastX&&null!=this._lastY&&"none"!==t.get("triggerOn")){var n=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout(function(){n.manuallyShowTip(t,e,i,{x:n._lastX,y:n._lastY})})}},manuallyShowTip:function(t,e,i,n){if(n.from!==this.uid&&!U_.node){var o=Pv(n,i);this._ticket="";var a=n.dataByCoordSys;if(n.tooltip&&null!=n.x&&null!=n.y){var r=dN;r.position=[n.x,n.y],r.update(),r.tooltip=n.tooltip,this._tryShow({offsetX:n.x,offsetY:n.y,target:r},o)}else if(a)this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,event:{},dataByCoordSys:n.dataByCoordSys,tooltipOption:n.tooltipOption},o);else if(null!=n.seriesIndex){if(this._manuallyAxisShowTip(t,e,i,n))return;var s=xP(n,e),l=s.point[0],u=s.point[1];null!=l&&null!=u&&this._tryShow({offsetX:l,offsetY:u,position:n.position,target:s.el,event:{}},o)}else null!=n.x&&null!=n.y&&(i.dispatchAction({type:"updateAxisPointer",x:n.x,y:n.y}),this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,target:i.getZr().findHover(n.x,n.y).target,event:{}},o))}},manuallyHideTip:function(t,e,i,n){var o=this._tooltipContent;!this._alwaysShowContent&&this._tooltipModel&&o.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=null,n.from!==this.uid&&this._hide(Pv(n,i))},_manuallyAxisShowTip:function(t,e,i,n){var o=n.seriesIndex,a=n.dataIndex,r=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=o&&null!=a&&null!=r){var s=e.getSeriesByIndex(o);if(s&&"axis"===(t=kv([s.getData().getItemModel(a),s,(s.coordinateSystem||{}).model,t])).get("trigger"))return i.dispatchAction({type:"updateAxisPointer",seriesIndex:o,dataIndex:a,position:n.position}),!0}},_tryShow:function(t,e){var i=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var n=t.dataByCoordSys;n&&n.length?this._showAxisTooltip(n,t):i&&null!=i.dataIndex?(this._lastDataByCoordSys=null,this._showSeriesItemTooltip(t,i,e)):i&&i.tooltip?(this._lastDataByCoordSys=null,this._showComponentItemTooltip(t,i,e)):(this._lastDataByCoordSys=null,this._hide(e))}},_showOrMove:function(t,e){var i=t.get("showDelay");e=m(e,this),clearTimeout(this._showTimout),i>0?this._showTimout=setTimeout(e,i):e()},_showAxisTooltip:function(t,e){var i=this._ecModel,o=this._tooltipModel,a=[e.offsetX,e.offsetY],r=[],s=[],l=kv([e.tooltipOption,o]),u=this._renderMode,h=this._newLine,c={};hN(t,function(t){hN(t.dataByAxis,function(t){var e=i.getComponent(t.axisDim+"Axis",t.axisIndex),o=t.value,a=[];if(e&&null!=o){var l=Im(o,e.axis,i,t.seriesDataIndices,t.valueLabelOpt);d(t.seriesDataIndices,function(r){var h=i.getSeriesByIndex(r.seriesIndex),d=r.dataIndexInside,f=h&&h.getDataParams(d);if(f.axisDim=t.axisDim,f.axisIndex=t.axisIndex,f.axisType=t.axisType,f.axisId=t.axisId,f.axisValue=Xl(e.axis,o),f.axisValueLabel=l,f){s.push(f);var p,g=h.formatTooltip(d,!0,null,u);if(w(g)){p=g.html;var m=g.markers;n(c,m)}else p=g;a.push(p)}});var f=l;"html"!==u?r.push(a.join(h)):r.push((f?ia(f)+h:"")+a.join(h))}})},this),r.reverse(),r=r.join(this._newLine+this._newLine);var f=e.position;this._showOrMove(l,function(){this._updateContentNotChangedOnAxis(t)?this._updatePosition(l,f,a[0],a[1],this._tooltipContent,s):this._showTooltipContent(l,r,s,Math.random(),a[0],a[1],f,void 0,c)})},_showSeriesItemTooltip:function(t,e,i){var n=this._ecModel,o=e.seriesIndex,a=n.getSeriesByIndex(o),r=e.dataModel||a,s=e.dataIndex,l=e.dataType,u=r.getData(),h=kv([u.getItemModel(s),r,a&&(a.coordinateSystem||{}).model,this._tooltipModel]),c=h.get("trigger");if(null==c||"item"===c){var d,f,p=r.getDataParams(s,l),g=r.formatTooltip(s,!1,l,this._renderMode);w(g)?(d=g.html,f=g.markers):(d=g,f=null);var m="item_"+r.name+"_"+s;this._showOrMove(h,function(){this._showTooltipContent(h,d,p,m,t.offsetX,t.offsetY,t.position,t.target,f)}),i({type:"showTip",dataIndexInside:s,dataIndex:u.getRawIndex(s),seriesIndex:o,from:this.uid})}},_showComponentItemTooltip:function(t,e,i){var n=e.tooltip;if("string"==typeof n){var o=n;n={content:o,formatter:o}}var a=new No(n,this._tooltipModel,this._ecModel),r=a.get("content"),s=Math.random();this._showOrMove(a,function(){this._showTooltipContent(a,r,a.get("formatterParams")||{},s,t.offsetX,t.offsetY,t.position,e)}),i({type:"showTip",from:this.uid})},_showTooltipContent:function(t,e,i,n,o,a,r,s,l){if(this._ticket="",t.get("showContent")&&t.get("show")){var u=this._tooltipContent,h=t.get("formatter");r=r||t.get("position");var c=e;if(h&&"string"==typeof h)c=na(h,i,!0);else if("function"==typeof h){var d=uN(function(e,n){e===this._ticket&&(u.setContent(n,l,t),this._updatePosition(t,r,o,a,u,i,s))},this);this._ticket=n,c=h(i,n,d)}u.setContent(c,l,t),u.show(t),this._updatePosition(t,r,o,a,u,i,s)}},_updatePosition:function(t,e,i,n,o,a,r){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var u=o.getSize(),h=t.get("align"),c=t.get("verticalAlign"),d=r&&r.getBoundingRect().clone();if(r&&d.applyTransform(r.transform),"function"==typeof e&&(e=e([i,n],a,o.el,d,{viewSize:[s,l],contentSize:u.slice()})),y(e))i=cN(e[0],s),n=cN(e[1],l);else if(w(e)){e.width=u[0],e.height=u[1];var f=ca(e,{width:s,height:l});i=f.x,n=f.y,h=null,c=null}else"string"==typeof e&&r?(i=(p=Ev(e,d,u))[0],n=p[1]):(i=(p=Nv(i,n,o,s,l,h?null:20,c?null:20))[0],n=p[1]);if(h&&(i-=Rv(h)?u[0]/2:"right"===h?u[0]:0),c&&(n-=Rv(c)?u[1]/2:"bottom"===c?u[1]:0),t.get("confine")){var p=Ov(i,n,o,s,l);i=p[0],n=p[1]}o.moveTo(i,n)},_updateContentNotChangedOnAxis:function(t){var e=this._lastDataByCoordSys,i=!!e&&e.length===t.length;return i&&hN(e,function(e,n){var o=e.dataByAxis||{},a=(t[n]||{}).dataByAxis||[];(i&=o.length===a.length)&&hN(o,function(t,e){var n=a[e]||{},o=t.seriesDataIndices||[],r=n.seriesDataIndices||[];(i&=t.value===n.value&&t.axisType===n.axisType&&t.axisId===n.axisId&&o.length===r.length)&&hN(o,function(t,e){var n=r[e];i&=t.seriesIndex===n.seriesIndex&&t.dataIndex===n.dataIndex})})}),this._lastDataByCoordSys=t,!!i},_hide:function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},dispose:function(t,e){U_.node||(this._tooltipContent.hide(),gm("itemTooltip",e))}}),Es({type:"showTip",event:"showTip",update:"tooltip:manuallyShowTip"},function(){}),Es({type:"hideTip",event:"hideTip",update:"tooltip:manuallyHideTip"},function(){}),Gv.prototype={constructor:Gv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToRadius:aD.prototype.dataToCoord,radiusToData:aD.prototype.coordToData},u(Gv,aD);var fN=Bi();Fv.prototype={constructor:Fv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToAngle:aD.prototype.dataToCoord,angleToData:aD.prototype.coordToData,calculateCategoryInterval:function(){var t=this,e=t.getLabelModel(),i=t.scale,n=i.getExtent(),o=i.count();if(n[1]-n[0]<1)return 0;var a=n[0],r=t.dataToCoord(a+1)-t.dataToCoord(a),s=Math.abs(r),l=ke(a,e.getFont(),"center","top"),u=Math.max(l.height,7)/s;isNaN(u)&&(u=1/0);var h=Math.max(0,Math.floor(u)),c=fN(t.model),d=c.lastAutoInterval,f=c.lastTickCount;return null!=d&&null!=f&&Math.abs(d-h)<=1&&Math.abs(f-o)<=1&&d>h?h=d:(c.lastTickCount=o,c.lastAutoInterval=h),h}},u(Fv,aD);var pN=function(t){this.name=t||"",this.cx=0,this.cy=0,this._radiusAxis=new Gv,this._angleAxis=new Fv,this._radiusAxis.polar=this._angleAxis.polar=this};pN.prototype={type:"polar",axisPointerEnabled:!0,constructor:pN,dimensions:["radius","angle"],model:null,containPoint:function(t){var e=this.pointToCoord(t);return this._radiusAxis.contain(e[0])&&this._angleAxis.contain(e[1])},containData:function(t){return this._radiusAxis.containData(t[0])&&this._angleAxis.containData(t[1])},getAxis:function(t){return this["_"+t+"Axis"]},getAxes:function(){return[this._radiusAxis,this._angleAxis]},getAxesByScale:function(t){var e=[],i=this._angleAxis,n=this._radiusAxis;return i.scale.type===t&&e.push(i),n.scale.type===t&&e.push(n),e},getAngleAxis:function(){return this._angleAxis},getRadiusAxis:function(){return this._radiusAxis},getOtherAxis:function(t){var e=this._angleAxis;return t===e?this._radiusAxis:e},getBaseAxis:function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAngleAxis()},getTooltipAxes:function(t){var e=null!=t&&"auto"!==t?this.getAxis(t):this.getBaseAxis();return{baseAxes:[e],otherAxes:[this.getOtherAxis(e)]}},dataToPoint:function(t,e){return this.coordToPoint([this._radiusAxis.dataToRadius(t[0],e),this._angleAxis.dataToAngle(t[1],e)])},pointToData:function(t,e){var i=this.pointToCoord(t);return[this._radiusAxis.radiusToData(i[0],e),this._angleAxis.angleToData(i[1],e)]},pointToCoord:function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=this.getAngleAxis(),o=n.getExtent(),a=Math.min(o[0],o[1]),r=Math.max(o[0],o[1]);n.inverse?a=r-360:r=a+360;var s=Math.sqrt(e*e+i*i);e/=s,i/=s;for(var l=Math.atan2(-i,e)/Math.PI*180,u=lr;)l+=360*u;return[s,l]},coordToPoint:function(t){var e=t[0],i=t[1]/180*Math.PI;return[Math.cos(i)*e+this.cx,-Math.sin(i)*e+this.cy]}};var gN=lI.extend({type:"polarAxis",axis:null,getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"polar",index:this.option.polarIndex,id:this.option.polarId})[0]}});n(gN.prototype,UA);var mN={angle:{startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:!1}},radius:{splitNumber:5}};ED("angle",gN,Wv,mN.angle),ED("radius",gN,Wv,mN.radius),Fs({type:"polar",dependencies:["polarAxis","angleAxis"],coordinateSystem:null,findAxisModel:function(t){var e;return this.ecModel.eachComponent(t,function(t){t.getCoordSysModel()===this&&(e=t)},this),e},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"80%"}});var vN={dimensions:pN.prototype.dimensions,create:function(t,e){var i=[];return t.eachComponent("polar",function(t,n){var o=new pN(n);o.update=Zv;var a=o.getRadiusAxis(),r=o.getAngleAxis(),s=t.findAxisModel("radiusAxis"),l=t.findAxisModel("angleAxis");Uv(a,s),Uv(r,l),Hv(o,t,e),i.push(o),t.coordinateSystem=o,o.model=t}),t.eachSeries(function(e){if("polar"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"polar",index:e.get("polarIndex"),id:e.get("polarId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}};Fa.register("polar",vN);var yN=["axisLine","axisLabel","axisTick","splitLine","splitArea"];XD.extend({type:"angleAxis",axisPointerClass:"PolarAxisPointer",render:function(t,e){if(this.group.removeAll(),t.get("show")){var n=t.axis,o=n.polar,a=o.getRadiusAxis().getExtent(),r=n.getTicksCoords(),s=f(n.getViewLabels(),function(t){return(t=i(t)).coord=n.dataToCoord(t.tickValue),t});Yv(s),Yv(r),d(yN,function(e){!t.get(e+".show")||n.scale.isBlank()&&"axisLine"!==e||this["_"+e](t,o,r,a,s)},this)}},_axisLine:function(t,e,i,n){var o=t.getModel("axisLine.lineStyle"),a=new sM({shape:{cx:e.cx,cy:e.cy,r:n[jv(e)]},style:o.getLineStyle(),z2:1,silent:!0});a.style.fill=null,this.group.add(a)},_axisTick:function(t,e,i,n){var o=t.getModel("axisTick"),a=(o.get("inside")?-1:1)*o.get("length"),s=n[jv(e)],l=f(i,function(t){return new _M({shape:Xv(e,[s,s+a],t.coord)})});this.group.add(OM(l,{style:r(o.getModel("lineStyle").getLineStyle(),{stroke:t.get("axisLine.lineStyle.color")})}))},_axisLabel:function(t,e,i,n,o){var a=t.getCategories(!0),r=t.getModel("axisLabel"),s=r.get("margin");d(o,function(i,o){var l=r,u=i.tickValue,h=n[jv(e)],c=e.coordToPoint([h+s,i.coord]),d=e.cx,f=e.cy,p=Math.abs(c[0]-d)/h<.3?"center":c[0]>d?"left":"right",g=Math.abs(c[1]-f)/h<.3?"middle":c[1]>f?"top":"bottom";a&&a[u]&&a[u].textStyle&&(l=new No(a[u].textStyle,r,r.ecModel));var m=new rM({silent:!0});this.group.add(m),mo(m.style,l,{x:c[0],y:c[1],textFill:l.getTextColor()||t.get("axisLine.lineStyle.color"),text:i.formattedLabel,textAlign:p,textVerticalAlign:g})},this)},_splitLine:function(t,e,i,n){var o=t.getModel("splitLine").getModel("lineStyle"),a=o.get("color"),s=0;a=a instanceof Array?a:[a];for(var l=[],u=0;u=0?"p":"n",M=y;v&&(n[r][b]||(n[r][b]={p:y,n:y}),M=n[r][b][S]);var I,T,A,D;if("radius"===h.dim){var C=h.dataToRadius(w)-y,L=a.dataToAngle(b);Math.abs(C)=0},kN.findTargetInfo=function(t,e){for(var i=this._targetInfoList,n=dy(e,t),o=0;o=0||AN(n,t.getAxis("y").model)>=0)&&a.push(t)}),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:a[0],coordSyses:a,getPanelRect:ON.grid,xAxisDeclared:r[t.id],yAxisDeclared:s[t.id]})}))},geo:function(t,e){TN(t.geoModels,function(t){var i=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:i,coordSyses:[i],getPanelRect:ON.geo})})}},NN=[function(t,e){var i=t.xAxisModel,n=t.yAxisModel,o=t.gridModel;return!o&&i&&(o=i.axis.grid.model),!o&&n&&(o=n.axis.grid.model),o&&o===e.gridModel},function(t,e){var i=t.geoModel;return i&&i===e.geoModel}],ON={grid:function(){return this.coordSys.grid.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(Ao(t)),e}},EN={lineX:DN(fy,0),lineY:DN(fy,1),rect:function(t,e,i){var n=e[CN[t]]([i[0][0],i[1][0]]),o=e[CN[t]]([i[0][1],i[1][1]]),a=[cy([n[0],o[0]]),cy([n[1],o[1]])];return{values:a,xyMinMax:a}},polygon:function(t,e,i){var n=[[1/0,-1/0],[1/0,-1/0]];return{values:f(i,function(i){var o=e[CN[t]](i);return n[0][0]=Math.min(n[0][0],o[0]),n[1][0]=Math.min(n[1][0],o[1]),n[0][1]=Math.max(n[0][1],o[0]),n[1][1]=Math.max(n[1][1],o[1]),o}),xyMinMax:n}}},RN={lineX:DN(py,0),lineY:DN(py,1),rect:function(t,e,i){return[[t[0][0]-i[0]*e[0][0],t[0][1]-i[0]*e[0][1]],[t[1][0]-i[1]*e[1][0],t[1][1]-i[1]*e[1][1]]]},polygon:function(t,e,i){return f(t,function(t,n){return[t[0]-i[0]*e[n][0],t[1]-i[1]*e[n][1]]})}},zN=["inBrush","outOfBrush"],BN="__ecBrushSelect",VN="__ecInBrushSelectEvent",GN=VT.VISUAL.BRUSH;zs(GN,function(t,e,i){t.eachComponent({mainType:"brush"},function(e){i&&"takeGlobalCursor"===i.type&&e.setBrushOption("brush"===i.key?i.brushOption:{brushType:!1}),(e.brushTargetManager=new hy(e.option,t)).setInputRanges(e.areas,t)})}),Bs(GN,function(t,e,n){var o,a,s=[];t.eachComponent({mainType:"brush"},function(e,n){function l(t){return"all"===m||v[t]}function u(t){return!!t.length}function h(t,e){var i=t.coordinateSystem;w|=i.hasAxisBrushed(),l(e)&&i.eachActiveState(t.getData(),function(t,e){"active"===t&&(x[e]=1)})}function c(i,n,o){var a=_y(i);if(a&&!wy(e,n)&&(d(b,function(n){a[n.brushType]&&e.brushTargetManager.controlSeries(n,i,t)&&o.push(n),w|=u(o)}),l(n)&&u(o))){var r=i.getData();r.each(function(t){xy(a,o,r,t)&&(x[t]=1)})}}var p={brushId:e.id,brushIndex:n,brushName:e.name,areas:i(e.areas),selected:[]};s.push(p);var g=e.option,m=g.brushLink,v=[],x=[],_=[],w=0;n||(o=g.throttleType,a=g.throttleDelay);var b=f(e.areas,function(t){return by(r({boundingRect:FN[t.brushType](t)},t))}),S=ty(e.option,zN,function(t){t.mappingMethod="fixed"});y(m)&&d(m,function(t){v[t]=1}),t.eachSeries(function(t,e){var i=_[e]=[];"parallel"===t.subType?h(t,e):c(t,e,i)}),t.eachSeries(function(t,e){var i={seriesId:t.id,seriesIndex:e,seriesName:t.name,dataIndex:[]};p.selected.push(i);var n=_y(t),o=_[e],a=t.getData(),r=l(e)?function(t){return x[t]?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"}:function(t){return xy(n,o,a,t)?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"};(l(e)?w:u(o))&&iy(zN,S,a,r)})}),vy(e,o,a,s,n)});var FN={lineX:B,lineY:B,rect:function(t){return Sy(t.range)},polygon:function(t){for(var e,i=t.range,n=0,o=i.length;ne[0][1]&&(e[0][1]=a[0]),a[1]e[1][1]&&(e[1][1]=a[1])}return e&&Sy(e)}},WN=["#ddd"];Fs({type:"brush",dependencies:["geo","grid","xAxis","yAxis","parallel","series"],defaultOption:{toolbox:null,brushLink:null,seriesIndex:"all",geoIndex:null,xAxisIndex:null,yAxisIndex:null,brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(120,140,180,0.3)",borderColor:"rgba(120,140,180,0.8)"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},areas:[],brushType:null,brushOption:{},coordInfoList:[],optionUpdated:function(t,e){var i=this.option;!e&&ey(i,t,["inBrush","outOfBrush"]);var n=i.inBrush=i.inBrush||{};i.outOfBrush=i.outOfBrush||{color:WN},n.hasOwnProperty("liftZ")||(n.liftZ=5)},setAreas:function(t){t&&(this.areas=f(t,function(t){return My(this.option,t)},this))},setBrushOption:function(t){this.brushOption=My(this.option,t),this.brushType=this.brushOption.brushType}});Ws({type:"brush",init:function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new zf(e.getZr())).on("brush",m(this._onBrush,this)).mount()},render:function(t){return this.model=t,Iy.apply(this,arguments)},updateTransform:Iy,updateView:Iy,dispose:function(){this._brushController.dispose()},_onBrush:function(t,e){var n=this.model.id;this.model.brushTargetManager.setOutputRanges(t,this.ecModel),(!e.isEnd||e.removeOnClick)&&this.api.dispatchAction({type:"brush",brushId:n,areas:i(t),$from:n})}}),Es({type:"brush",event:"brush"},function(t,e){e.eachComponent({mainType:"brush",query:t},function(e){e.setAreas(t.areas)})}),Es({type:"brushSelect",event:"brushSelected",update:"none"},function(){});var HN={},ZN=rT.toolbox.brush;Dy.defaultOption={show:!0,type:["rect","polygon","lineX","lineY","keep","clear"],icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:i(ZN.title)};var UN=Dy.prototype;UN.render=UN.updateView=function(t,e,i){var n,o,a;e.eachComponent({mainType:"brush"},function(t){n=t.brushType,o=t.brushOption.brushMode||"single",a|=t.areas.length}),this._brushType=n,this._brushMode=o,d(t.get("type",!0),function(e){t.setIconStatus(e,("keep"===e?"multiple"===o:"clear"===e?a:e===n)?"emphasis":"normal")})},UN.getIcons=function(){var t=this.model,e=t.get("icon",!0),i={};return d(t.get("type",!0),function(t){e[t]&&(i[t]=e[t])}),i},UN.onclick=function(t,e,i){var n=this._brushType,o=this._brushMode;"clear"===i?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===i?n:n!==i&&i,brushMode:"keep"===i?"multiple"===o?"single":"multiple":o}})},Ty("brush",Dy),Ns(function(t,e){var i=t&&t.brush;if(y(i)||(i=i?[i]:[]),i.length){var n=[];d(i,function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(n=n.concat(e))});var o=t&&t.toolbox;y(o)&&(o=o[0]),o||(o={feature:{}},t.toolbox=[o]);var a=o.feature||(o.feature={}),r=a.brush||(a.brush={}),s=r.type||(r.type=[]);s.push.apply(s,n),Jv(s),e&&!s.length&&s.push.apply(s,SN)}});Cy.prototype={constructor:Cy,type:"calendar",dimensions:["time","value"],getDimensionsInfo:function(){return[{name:"time",type:"time"},"value"]},getRangeInfo:function(){return this._rangeInfo},getModel:function(){return this._model},getRect:function(){return this._rect},getCellWidth:function(){return this._sw},getCellHeight:function(){return this._sh},getOrient:function(){return this._orient},getFirstDayOfWeek:function(){return this._firstDayOfWeek},getDateInfo:function(t){var e=(t=Yo(t)).getFullYear(),i=t.getMonth()+1;i=i<10?"0"+i:i;var n=t.getDate();n=n<10?"0"+n:n;var o=t.getDay();return o=Math.abs((o+7-this.getFirstDayOfWeek())%7),{y:e,m:i,d:n,day:o,time:t.getTime(),formatedDate:e+"-"+i+"-"+n,date:t}},getNextNDay:function(t,e){return 0===(e=e||0)?this.getDateInfo(t):((t=new Date(this.getDateInfo(t).time)).setDate(t.getDate()+e),this.getDateInfo(t))},update:function(t,e){function i(t,e){return null!=t[e]&&"auto"!==t[e]}this._firstDayOfWeek=+this._model.getModel("dayLabel").get("firstDay"),this._orient=this._model.get("orient"),this._lineWidth=this._model.getModel("itemStyle").getItemStyle().lineWidth||0,this._rangeInfo=this._getRangeInfo(this._initRangeOption());var n=this._rangeInfo.weeks||1,o=["width","height"],a=this._model.get("cellSize").slice(),r=this._model.getBoxLayoutParams(),s="horizontal"===this._orient?[n,7]:[7,n];d([0,1],function(t){i(a,t)&&(r[o[t]]=a[t]*s[t])});var l={width:e.getWidth(),height:e.getHeight()},u=this._rect=ca(r,l);d([0,1],function(t){i(a,t)||(a[t]=u[o[t]]/s[t])}),this._sw=a[0],this._sh=a[1]},dataToPoint:function(t,e){y(t)&&(t=t[0]),null==e&&(e=!0);var i=this.getDateInfo(t),n=this._rangeInfo,o=i.formatedDate;if(e&&!(i.time>=n.start.time&&i.timea.end.time&&t.reverse(),t},_getRangeInfo:function(t){var e;(t=[this.getDateInfo(t[0]),this.getDateInfo(t[1])])[0].time>t[1].time&&(e=!0,t.reverse());var i=Math.floor(t[1].time/864e5)-Math.floor(t[0].time/864e5)+1,n=new Date(t[0].time),o=n.getDate(),a=t[1].date.getDate();if(n.setDate(o+i-1),n.getDate()!==a)for(var r=n.getTime()-t[1].time>0?1:-1;n.getDate()!==a&&(n.getTime()-t[1].time)*r>0;)i-=r,n.setDate(o+i-1);var s=Math.floor((i+t[0].day+6)/7),l=e?1-s:s-1;return e&&t.reverse(),{range:[t[0].formatedDate,t[1].formatedDate],start:t[0],end:t[1],allDay:i,weeks:s,nthWeek:l,fweek:t[0].day,lweek:t[1].day}},_getDateByWeeksAndDay:function(t,e,i){var n=this._getRangeInfo(i);if(t>n.weeks||0===t&&en.lweek)return!1;var o=7*(t-1)-n.fweek+e,a=new Date(n.start.time);return a.setDate(n.start.d+o),this.getDateInfo(a)}},Cy.dimensions=Cy.prototype.dimensions,Cy.getDimensionsInfo=Cy.prototype.getDimensionsInfo,Cy.create=function(t,e){var i=[];return t.eachComponent("calendar",function(n){var o=new Cy(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeries(function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("calendarIndex")||0])}),i},Fa.register("calendar",Cy);var XN=lI.extend({type:"calendar",coordinateSystem:null,defaultOption:{zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},init:function(t,e,i,n){var o=ga(t);XN.superApply(this,"init",arguments),ky(t,o)},mergeOption:function(t,e){XN.superApply(this,"mergeOption",arguments),ky(this.option,t)}}),jN={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},YN={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]};Ws({type:"calendar",_tlpoints:null,_blpoints:null,_firstDayOfMonth:null,_firstDayPoints:null,render:function(t,e,i){var n=this.group;n.removeAll();var o=t.coordinateSystem,a=o.getRangeInfo(),r=o.getOrient();this._renderDayRect(t,a,n),this._renderLines(t,a,r,n),this._renderYearText(t,a,r,n),this._renderMonthText(t,r,n),this._renderWeekText(t,a,r,n)},_renderDayRect:function(t,e,i){for(var n=t.coordinateSystem,o=t.getModel("itemStyle").getItemStyle(),a=n.getCellWidth(),r=n.getCellHeight(),s=e.start.time;s<=e.end.time;s=n.getNextNDay(s,1).time){var l=n.dataToRect([s],!1).tl,u=new yM({shape:{x:l[0],y:l[1],width:a,height:r},cursor:"default",style:o});i.add(u)}},_renderLines:function(t,e,i,n){function o(e){a._firstDayOfMonth.push(r.getDateInfo(e)),a._firstDayPoints.push(r.dataToRect([e],!1).tl);var o=a._getLinePointsOfOneWeek(t,e,i);a._tlpoints.push(o[0]),a._blpoints.push(o[o.length-1]),l&&a._drawSplitline(o,s,n)}var a=this,r=t.coordinateSystem,s=t.getModel("splitLine.lineStyle").getLineStyle(),l=t.get("splitLine.show"),u=s.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var h=e.start,c=0;h.time<=e.end.time;c++){o(h.formatedDate),0===c&&(h=r.getDateInfo(e.start.y+"-"+e.start.m));var d=h.date;d.setMonth(d.getMonth()+1),h=r.getDateInfo(d)}o(r.getNextNDay(e.end.time,1).formatedDate),l&&this._drawSplitline(a._getEdgesPoints(a._tlpoints,u,i),s,n),l&&this._drawSplitline(a._getEdgesPoints(a._blpoints,u,i),s,n)},_getEdgesPoints:function(t,e,i){var n=[t[0].slice(),t[t.length-1].slice()],o="horizontal"===i?0:1;return n[0][o]=n[0][o]-e/2,n[1][o]=n[1][o]+e/2,n},_drawSplitline:function(t,e,i){var n=new gM({z2:20,shape:{points:t},style:e});i.add(n)},_getLinePointsOfOneWeek:function(t,e,i){var n=t.coordinateSystem;e=n.getDateInfo(e);for(var o=[],a=0;a<7;a++){var r=n.getNextNDay(e.time,a),s=n.dataToRect([r.time],!1);o[2*r.day]=s.tl,o[2*r.day+1]=s["horizontal"===i?"bl":"tr"]}return o},_formatterLabel:function(t,e){return"string"==typeof t&&t?oa(t,e):"function"==typeof t?t(e):e.nameMap},_yearTextPositionControl:function(t,e,i,n,o){e=e.slice();var a=["center","bottom"];"bottom"===n?(e[1]+=o,a=["center","top"]):"left"===n?e[0]-=o:"right"===n?(e[0]+=o,a=["center","top"]):e[1]-=o;var r=0;return"left"!==n&&"right"!==n||(r=Math.PI/2),{rotation:r,position:e,style:{textAlign:a[0],textVerticalAlign:a[1]}}},_renderYearText:function(t,e,i,n){var o=t.getModel("yearLabel");if(o.get("show")){var a=o.get("margin"),r=o.get("position");r||(r="horizontal"!==i?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===i?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var f=o.get("formatter"),p={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(f,p),m=new rM({z2:30});mo(m.style,o,{text:g}),m.attr(this._yearTextPositionControl(m,c[r],i,r,a)),n.add(m)}},_monthTextPositionControl:function(t,e,i,n,o){var a="left",r="top",s=t[0],l=t[1];return"horizontal"===i?(l+=o,e&&(a="center"),"start"===n&&(r="bottom")):(s+=o,e&&(r="middle"),"start"===n&&(a="right")),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderMonthText:function(t,e,i){var n=t.getModel("monthLabel");if(n.get("show")){var o=n.get("nameMap"),r=n.get("margin"),s=n.get("position"),l=n.get("align"),u=[this._tlpoints,this._blpoints];_(o)&&(o=jN[o.toUpperCase()]||[]);var h="start"===s?0:1,c="horizontal"===e?0:1;r="start"===s?-r:r;for(var d="center"===l,f=0;f=r[0]&&t<=r[1]}if(t===this._dataZoomModel){var n=this._dimName,o=this.getTargetSeriesModels(),a=t.get("filterMode"),r=this._valueWindow;"none"!==a&&$N(o,function(t){var e=t.getData(),o=e.mapDimension(n,!0);o.length&&("weakFilter"===a?e.filterSelf(function(t){for(var i,n,a,s=0;sr[1];if(u&&!h&&!c)return!0;u&&(a=!0),h&&(i=!0),c&&(n=!0)}return a&&i&&n}):$N(o,function(n){if("empty"===a)t.setData(e.map(n,function(t){return i(t)?t:NaN}));else{var o={};o[n]=r,e.selectRange(o)}}),$N(o,function(t){e.setApproximateExtent(r,t)}))})}}};var tO=d,eO=KN,iO=Fs({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,i){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var n=By(t);this.mergeDefaultAndTheme(t,i),this.doInit(n)},mergeOption:function(t){var e=By(t);n(this.option,t,!0),this.doInit(e)},doInit:function(t){var e=this.option;U_.canvasSupported||(e.realtime=!1),this._setDefaultThrottle(t),Vy(this,t),tO([["start","startValue"],["end","endValue"]],function(t,i){"value"===this._rangePropMode[i]&&(e[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var t=this._axisProxies;this.eachTargetAxis(function(e,i,n,o){var a=this.dependentModels[e.axis][i],r=a.__dzAxisProxy||(a.__dzAxisProxy=new QN(e.name,i,this,o));t[e.name+"_"+i]=r},this)},_resetTarget:function(){var t=this.option,e=this._judgeAutoMode();eO(function(e){var i=e.axisIndex;t[i]=Di(t[i])},this),"axisIndex"===e?this._autoSetAxisIndex():"orient"===e&&this._autoSetOrient()},_judgeAutoMode:function(){var t=this.option,e=!1;eO(function(i){null!=t[i.axisIndex]&&(e=!0)},this);var i=t.orient;return null==i&&e?"orient":e?void 0:(null==i&&(t.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var t=!0,e=this.get("orient",!0),i=this.option,n=this.dependentModels;if(t){var o="vertical"===e?"y":"x";n[o+"Axis"].length?(i[o+"AxisIndex"]=[0],t=!1):tO(n.singleAxis,function(n){t&&n.get("orient",!0)===e&&(i.singleAxisIndex=[n.componentIndex],t=!1)})}t&&eO(function(e){if(t){var n=[],o=this.dependentModels[e.axis];if(o.length&&!n.length)for(var a=0,r=o.length;a0?100:20}},getFirstTargetAxisModel:function(){var t;return eO(function(e){if(null==t){var i=this.get(e.axisIndex);i.length&&(t=this.dependentModels[e.axis][i[0]])}},this),t},eachTargetAxis:function(t,e){var i=this.ecModel;eO(function(n){tO(this.get(n.axisIndex),function(o){t.call(e,n,o,this,i)},this)},this)},getAxisProxy:function(t,e){return this._axisProxies[t+"_"+e]},getAxisModel:function(t,e){var i=this.getAxisProxy(t,e);return i&&i.getAxisModel()},setRawRange:function(t,e){var i=this.option;tO([["start","startValue"],["end","endValue"]],function(e){null==t[e[0]]&&null==t[e[1]]||(i[e[0]]=t[e[0]],i[e[1]]=t[e[1]])},this),!e&&Vy(this,t)},getPercentRange:function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},getValueRange:function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var i=this.findRepresentativeAxisProxy();return i?i.getDataValueWindow():void 0},findRepresentativeAxisProxy:function(t){if(t)return t.__dzAxisProxy;var e=this._axisProxies;for(var i in e)if(e.hasOwnProperty(i)&&e[i].hostedBy(this))return e[i];for(var i in e)if(e.hasOwnProperty(i)&&!e[i].hostedBy(this))return e[i]},getRangePropMode:function(){return this._rangePropMode.slice()}}),nO=qI.extend({type:"dataZoom",render:function(t,e,i,n){this.dataZoomModel=t,this.ecModel=e,this.api=i},getTargetCoordInfo:function(){function t(t,e,i,n){for(var o,a=0;a0&&e%g)p+=f;else{var i=null==t||isNaN(t)||""===t,n=i?0:aO(t,a,u,!0);i&&!l&&e?(c.push([c[c.length-1][0],0]),d.push([d[d.length-1][0],0])):!i&&l&&(c.push([p,0]),d.push([p,0])),c.push([p,n]),d.push([p,n]),p+=f,l=i}});var m=this.dataZoomModel;this._displayables.barGroup.add(new pM({shape:{points:c},style:r({fill:m.get("dataBackgroundColor")},m.getModel("dataBackground.areaStyle").getAreaStyle()),silent:!0,z2:-20})),this._displayables.barGroup.add(new gM({shape:{points:d},style:m.getModel("dataBackground.lineStyle").getLineStyle(),silent:!0,z2:-19}))}}},_prepareDataShadowInfo:function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var i,n=this.ecModel;return t.eachTargetAxis(function(o,a){d(t.getAxisProxy(o.name,a).getTargetSeriesModels(),function(t){if(!(i||!0!==e&&l(cO,t.get("type"))<0)){var r,s=n.getComponent(o.axis,a).axis,u=Gy(o.name),h=t.coordinateSystem;null!=u&&h.getOtherAxis&&(r=h.getOtherAxis(s).inverse),u=t.getData().mapDimension(u),i={thisAxis:s,series:t,thisDim:o.name,otherDim:u,otherAxisInverse:r}}},this)},this),i}},_renderHandle:function(){var t=this._displayables,e=t.handles=[],i=t.handleLabels=[],n=this._displayables.barGroup,o=this._size,a=this.dataZoomModel;n.add(t.filler=new oO({draggable:!0,cursor:Fy(this._orient),drift:sO(this._onDragMove,this,"all"),onmousemove:function(t){mw(t.event)},ondragstart:sO(this._showDataInfo,this,!0),ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1),style:{fill:a.get("fillerColor"),textPosition:"inside"}})),n.add(new oO($n({silent:!0,shape:{x:0,y:0,width:o[0],height:o[1]},style:{stroke:a.get("dataBackgroundColor")||a.get("borderColor"),lineWidth:1,fill:"rgba(0,0,0,0)"}}))),lO([0,1],function(t){var o=Po(a.get("handleIcon"),{cursor:Fy(this._orient),draggable:!0,drift:sO(this._onDragMove,this,t),onmousemove:function(t){mw(t.event)},ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1)},{x:-1,y:0,width:2,height:2}),r=o.getBoundingRect();this._handleHeight=Vo(a.get("handleSize"),this._size[1]),this._handleWidth=r.width/r.height*this._handleHeight,o.setStyle(a.getModel("handleStyle").getItemStyle());var s=a.get("handleColor");null!=s&&(o.style.fill=s),n.add(e[t]=o);var l=a.textStyleModel;this.group.add(i[t]=new rM({silent:!0,invisible:!0,style:{x:0,y:0,text:"",textVerticalAlign:"middle",textAlign:"center",textFill:l.getTextColor(),textFont:l.getFont()},z2:10}))},this)},_resetInterval:function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[aO(t[0],[0,100],e,!0),aO(t[1],[0,100],e,!0)]},_updateInterval:function(t,e){var i=this.dataZoomModel,n=this._handleEnds,o=this._getViewExtent(),a=i.findRepresentativeAxisProxy().getMinMaxSpan(),r=[0,100];QL(e,n,o,i.get("zoomLock")?"all":t,null!=a.minSpan?aO(a.minSpan,r,o,!0):null,null!=a.maxSpan?aO(a.maxSpan,r,o,!0):null);var s=this._range,l=this._range=rO([aO(n[0],o,r,!0),aO(n[1],o,r,!0)]);return!s||s[0]!==l[0]||s[1]!==l[1]},_updateView:function(t){var e=this._displayables,i=this._handleEnds,n=rO(i.slice()),o=this._size;lO([0,1],function(t){var n=e.handles[t],a=this._handleHeight;n.attr({scale:[a/2,a/2],position:[i[t],o[1]/2-a/2]})},this),e.filler.setShape({x:n[0],y:0,width:n[1]-n[0],height:o[1]}),this._updateDataInfo(t)},_updateDataInfo:function(t){function e(t){var e=Ao(n.handles[t].parent,this.group),i=Co(0===t?"right":"left",e),s=this._handleWidth/2+hO,l=Do([c[t]+(0===t?-s:s),this._size[1]/2],e);o[t].setStyle({x:l[0],y:l[1],textVerticalAlign:a===uO?"middle":i,textAlign:a===uO?i:"center",text:r[t]})}var i=this.dataZoomModel,n=this._displayables,o=n.handleLabels,a=this._orient,r=["",""];if(i.get("showDetail")){var s=i.findRepresentativeAxisProxy();if(s){var l=s.getAxisModel().axis,u=this._range,h=t?s.calculateDataWindow({start:u[0],end:u[1]}).valueWindow:s.getDataValueWindow();r=[this._formatLabel(h[0],l),this._formatLabel(h[1],l)]}}var c=rO(this._handleEnds.slice());e.call(this,0),e.call(this,1)},_formatLabel:function(t,e){var i=this.dataZoomModel,n=i.get("labelFormatter"),o=i.get("labelPrecision");null!=o&&"auto"!==o||(o=e.getPixelPrecision());var a=null==t||isNaN(t)?"":"category"===e.type||"time"===e.type?e.scale.getLabel(Math.round(t)):t.toFixed(Math.min(o,20));return x(n)?n(t,a):_(n)?n.replace("{value}",a):a},_showDataInfo:function(t){t=this._dragging||t;var e=this._displayables.handleLabels;e[0].attr("invisible",!t),e[1].attr("invisible",!t)},_onDragMove:function(t,e,i){this._dragging=!0;var n=Do([e,i],this._displayables.barGroup.getLocalTransform(),!0),o=this._updateInterval(t,n[0]),a=this.dataZoomModel.get("realtime");this._updateView(!a),o&&a&&this._dispatchZoomAction()},_onDragEnd:function(){this._dragging=!1,this._showDataInfo(!1),!this.dataZoomModel.get("realtime")&&this._dispatchZoomAction()},_onClickPanelClick:function(t){var e=this._size,i=this._displayables.barGroup.transformCoordToLocal(t.offsetX,t.offsetY);if(!(i[0]<0||i[0]>e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var t;if(lO(this.getTargetCoordInfo(),function(e){if(!t&&e.length){var i=e[0].model.coordinateSystem;t=i.getRect&&i.getRect()}}),!t){var e=this.api.getWidth(),i=this.api.getHeight();t={x:.2*e,y:.2*i,width:.6*e,height:.6*i}}return t}});iO.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var fO="\0_ec_dataZoom_roams",pO=m,gO=nO.extend({type:"dataZoom.inside",init:function(t,e){this._range},render:function(t,e,i,n){gO.superApply(this,"render",arguments),this._range=t.getPercentRange(),d(this.getTargetCoordInfo(),function(e,n){var o=f(e,function(t){return Zy(t.model)});d(e,function(e){var a=e.model,r={};d(["pan","zoom","scrollMove"],function(t){r[t]=pO(mO[t],this,e,n)},this),Wy(i,{coordId:Zy(a),allCoordIds:o,containsPoint:function(t,e,i){return a.coordinateSystem.containPoint([e,i])},dataZoomId:t.id,dataZoomModel:t,getRange:r})},this)},this)},dispose:function(){Hy(this.api,this.dataZoomModel.id),gO.superApply(this,"dispose",arguments),this._range=null}}),mO={zoom:function(t,e,i,n){var o=this._range,a=o.slice(),r=t.axisModels[0];if(r){var s=vO[e](null,[n.originX,n.originY],r,i,t),l=(s.signal>0?s.pixelStart+s.pixelLength-s.pixel:s.pixel-s.pixelStart)/s.pixelLength*(a[1]-a[0])+a[0],u=Math.max(1/n.scale,0);a[0]=(a[0]-l)*u+l,a[1]=(a[1]-l)*u+l;var h=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return QL(0,a,[0,100],0,h.minSpan,h.maxSpan),this._range=a,o[0]!==a[0]||o[1]!==a[1]?a:void 0}},pan:Ky(function(t,e,i,n,o,a){var r=vO[n]([a.oldX,a.oldY],[a.newX,a.newY],e,o,i);return r.signal*(t[1]-t[0])*r.pixel/r.pixelLength}),scrollMove:Ky(function(t,e,i,n,o,a){return vO[n]([0,0],[a.scrollDelta,a.scrollDelta],e,o,i).signal*(t[1]-t[0])*a.scrollDelta})},vO={grid:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem.getRect();return t=t||[0,0],"x"===a.dim?(r.pixel=e[0]-t[0],r.pixelLength=s.width,r.pixelStart=s.x,r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=s.height,r.pixelStart=s.y,r.signal=a.inverse?-1:1),r},polar:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),u=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===i.mainType?(r.pixel=e[0]-t[0],r.pixelLength=l[1]-l[0],r.pixelStart=l[0],r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=u[1]-u[0],r.pixelStart=u[0],r.signal=a.inverse?-1:1),r},singleAxis:function(t,e,i,n,o){var a=i.axis,r=o.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===a.orient?(s.pixel=e[0]-t[0],s.pixelLength=r.width,s.pixelStart=r.x,s.signal=a.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=r.height,s.pixelStart=r.y,s.signal=a.inverse?-1:1),s}};Os({getTargetSeries:function(t){var e=R();return t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){d(n.getAxisProxy(t.name,i).getTargetSeriesModels(),function(t){e.set(t.uid,t)})})}),e},modifyOutputEnd:!0,overallReset:function(t,e){t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).reset(n,e)}),t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).filterData(n,e)})}),t.eachComponent("dataZoom",function(t){var e=t.findRepresentativeAxisProxy(),i=e.getDataPercentWindow(),n=e.getDataValueWindow();t.setRawRange({start:i[0],end:i[1],startValue:n[0],endValue:n[1]},!0)})}}),Es("dataZoom",function(t,e){var i=Ny(m(e.eachComponent,e,"dataZoom"),KN,function(t,e){return t.get(e.axisIndex)}),n=[];e.eachComponent({mainType:"dataZoom",query:t},function(t,e){n.push.apply(n,i(t).nodes)}),d(n,function(e,i){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})})});var yO=d,xO=function(t){var e=t&&t.visualMap;y(e)||(e=e?[e]:[]),yO(e,function(t){if(t){$y(t,"splitList")&&!$y(t,"pieces")&&(t.pieces=t.splitList,delete t.splitList);var e=t.pieces;e&&y(e)&&yO(e,function(t){w(t)&&($y(t,"start")&&!$y(t,"min")&&(t.min=t.start),$y(t,"end")&&!$y(t,"max")&&(t.max=t.end))})}})};lI.registerSubTypeDefaulter("visualMap",function(t){return t.categories||(t.pieces?t.pieces.length>0:t.splitNumber>0)&&!t.calculable?"piecewise":"continuous"});var _O=VT.VISUAL.COMPONENT;Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=[];return e.eachComponent("visualMap",function(e){var n=t.pipelineContext;!e.isTargetSeries(t)||n&&n.large||i.push(ny(e.stateList,e.targetVisuals,m(e.getValueState,e),e.getDataDimension(t.getData())))}),i}}),Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=t.getData(),n=[];e.eachComponent("visualMap",function(e){if(e.isTargetSeries(t)){var o=e.getVisualMeta(m(Jy,null,t,e))||{stops:[],outerColors:[]},a=e.getDataDimension(i),r=i.getDimensionInfo(a);null!=r&&(o.dimension=r.index,n.push(o))}}),t.getData().setVisual("visualMeta",n)}});var wO={get:function(t,e,n){var o=i((bO[t]||{})[e]);return n&&y(o)?o[o.length-1]:o}},bO={color:{active:["#006edd","#e0ffff"],inactive:["rgba(0,0,0,0)"]},colorHue:{active:[0,360],inactive:[0,0]},colorSaturation:{active:[.3,1],inactive:[0,0]},colorLightness:{active:[.9,.5],inactive:[0,0]},colorAlpha:{active:[.3,1],inactive:[0,0]},opacity:{active:[.3,1],inactive:[0,0]},symbol:{active:["circle","roundRect","diamond"],inactive:["none"]},symbolSize:{active:[10,50],inactive:[0,0]}},SO=hL.mapVisual,MO=hL.eachVisual,IO=y,TO=d,AO=Fo,DO=Bo,CO=B,LO=Fs({type:"visualMap",dependencies:["series"],stateList:["inRange","outOfRange"],replacableOptionKeys:["inRange","outOfRange","target","controller","color"],dataBound:[-1/0,1/0],layoutMode:{type:"box",ignoreSize:!0},defaultOption:{show:!0,zlevel:0,z:4,seriesIndex:"all",min:0,max:200,dimension:null,inRange:null,outOfRange:null,left:0,right:null,top:null,bottom:0,itemWidth:null,itemHeight:null,inverse:!1,orient:"vertical",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",contentColor:"#5793f3",inactiveColor:"#aaa",borderWidth:0,padding:5,textGap:10,precision:0,color:null,formatter:null,text:null,textStyle:{color:"#333"}},init:function(t,e,i){this._dataExtent,this.targetVisuals={},this.controllerVisuals={},this.textStyleModel,this.itemSize,this.mergeDefaultAndTheme(t,i)},optionUpdated:function(t,e){var i=this.option;U_.canvasSupported||(i.realtime=!1),!e&&ey(i,t,this.replacableOptionKeys),this.textStyleModel=this.getModel("textStyle"),this.resetItemSize(),this.completeVisualOption()},resetVisual:function(t){var e=this.stateList;t=m(t,this),this.controllerVisuals=ty(this.option.controller,e,t),this.targetVisuals=ty(this.option.target,e,t)},getTargetSeriesIndices:function(){var t=this.option.seriesIndex,e=[];return null==t||"all"===t?this.ecModel.eachSeries(function(t,i){e.push(i)}):e=Di(t),e},eachTargetSeries:function(t,e){d(this.getTargetSeriesIndices(),function(i){t.call(e,this.ecModel.getSeriesByIndex(i))},this)},isTargetSeries:function(t){var e=!1;return this.eachTargetSeries(function(i){i===t&&(e=!0)}),e},formatValueText:function(t,e,i){function n(t){return t===l[0]?"min":t===l[1]?"max":(+t).toFixed(Math.min(s,20))}var o,a,r=this.option,s=r.precision,l=this.dataBound,u=r.formatter;return i=i||["<",">"],y(t)&&(t=t.slice(),o=!0),a=e?t:o?[n(t[0]),n(t[1])]:n(t),_(u)?u.replace("{value}",o?a[0]:a).replace("{value2}",o?a[1]:a):x(u)?o?u(t[0],t[1]):u(t):o?t[0]===l[0]?i[0]+" "+a[1]:t[1]===l[1]?i[1]+" "+a[0]:a[0]+" - "+a[1]:a},resetExtent:function(){var t=this.option,e=AO([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;o>=0;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){function t(t){IO(o.color)&&!t.inRange&&(t.inRange={color:o.color.slice().reverse()}),t.inRange=t.inRange||{color:e.get("gradientColor")},TO(this.stateList,function(e){var i=t[e];if(_(i)){var n=wO.get(i,"active",l);n?(t[e]={},t[e][i]=n):delete t[e]}},this)}var e=this.ecModel,o=this.option,a={inRange:o.inRange,outOfRange:o.outOfRange},r=o.target||(o.target={}),s=o.controller||(o.controller={});n(r,a),n(s,a);var l=this.isCategory();t.call(this,r),t.call(this,s),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},TO(n,function(t,e){if(hL.isValidType(e)){var i=wO.get(e,"inactive",l);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,r,"inRange","outOfRange"),function(t){var e=(t.inRange||{}).symbol||(t.outOfRange||{}).symbol,n=(t.inRange||{}).symbolSize||(t.outOfRange||{}).symbolSize,o=this.get("inactiveColor");TO(this.stateList,function(a){var r=this.itemSize,s=t[a];s||(s=t[a]={color:l?o:[o]}),null==s.symbol&&(s.symbol=e&&i(e)||(l?"roundRect":["roundRect"])),null==s.symbolSize&&(s.symbolSize=n&&i(n)||(l?r[0]:[r[0],r[0]])),s.symbol=SO(s.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var u=s.symbolSize;if(null!=u){var h=-1/0;MO(u,function(t){t>h&&(h=t)}),s.symbolSize=SO(u,function(t){return DO(t,[0,h],[0,r[0]],!0)})}},this)}.call(this,s)},resetItemSize:function(){this.itemSize=[parseFloat(this.get("itemWidth")),parseFloat(this.get("itemHeight"))]},isCategory:function(){return!!this.option.categories},setSelected:CO,getValueState:CO,getVisualMeta:CO}),kO=[20,140],PO=LO.extend({type:"visualMap.continuous",defaultOption:{align:"auto",calculable:!1,range:null,realtime:!0,itemHeight:null,itemWidth:null,hoverLink:!0,hoverLinkDataSize:null,hoverLinkOnHandle:null},optionUpdated:function(t,e){PO.superApply(this,"optionUpdated",arguments),this.resetExtent(),this.resetVisual(function(t){t.mappingMethod="linear",t.dataExtent=this.getExtent()}),this._resetRange()},resetItemSize:function(){PO.superApply(this,"resetItemSize",arguments);var t=this.itemSize;"horizontal"===this._orient&&t.reverse(),(null==t[0]||isNaN(t[0]))&&(t[0]=kO[0]),(null==t[1]||isNaN(t[1]))&&(t[1]=kO[1])},_resetRange:function(){var t=this.getExtent(),e=this.option.range;!e||e.auto?(t.auto=1,this.option.range=t):y(e)&&(e[0]>e[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){LO.prototype.completeVisualOption.apply(this,arguments),d(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Fo((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){t[0]<=e&&e<=t[1]&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getVisualMeta:function(t){function e(e,i){o.push({value:e,color:t(e,i)})}for(var i=Qy(0,0,this.getExtent()),n=Qy(0,0,this.option.range.slice()),o=[],a=0,r=0,s=n.length,l=i.length;rt[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new tb("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(t,e){if(this._useHandle){var i=this._shapes,n=this.visualMapModel,o=i.handleThumbs,a=i.handleLabels;EO([0,1],function(r){var s=o[r];s.setStyle("fill",e.handlesColor[r]),s.position[1]=t[r];var l=Do(i.handleLabelPoints[r],Ao(s,this.group));a[r].setStyle({x:l[0],y:l[1],text:n.formatValueText(this._dataInterval[r]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===r?"bottom":"top":"left",i.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=OO(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",ox(!!i,n,l,r[1]));var c={convertOpacityToAlpha:!0},d=this.getControllerVisual(t,"color",c);h.setStyle("fill",d);var f=Do(u.indicatorLabelPoint,Ao(h,this.group)),p=u.indicatorLabel;p.attr("invisible",!1);var g=this._applyTransform("left",u.barGroup),m=this._orient;p.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===m?g:"middle",textAlign:"horizontal"===m?"center":g,x:f[0],y:f[1]})}},_enableHoverLinkToSeries:function(){var t=this;this._shapes.barGroup.on("mousemove",function(e){if(t._hovering=!0,!t._dragging){var i=t.visualMapModel.itemSize,n=t._applyTransform([e.offsetX,e.offsetY],t._shapes.barGroup,!0,!0);n[1]=RO(zO(0,n[1]),i[1]),t._doHoverLinkToSeries(n[1],0<=n[0]&&n[0]<=i[0])}}).on("mouseout",function(){t._hovering=!1,!t._dragging&&t._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=RO(zO(o[0],t),o[1]);var r=ax(i,a,o),s=[t-r,t+r],l=OO(t,o,a,!0),u=[OO(s[0],o,a,!0),OO(s[1],o,a,!0)];s[0]o[1]&&(u[1]=1/0),e&&(u[0]===-1/0?this._showIndicator(l,u[1],"< ",r):u[1]===1/0?this._showIndicator(l,u[0],"> ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||rx(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=Ri(h,c);this._dispatchHighDown("downplay",ex(d[0])),this._dispatchHighDown("highlight",ex(d[1]))}},_hoverLinkFromSeriesMouseOver:function(t){var e=t.target,i=this.visualMapModel;if(e&&null!=e.dataIndex){var n=this.ecModel.getSeriesByIndex(e.seriesIndex);if(i.isTargetSeries(n)){var o=n.getData(e.dataType),a=o.get(i.getDataDimension(o),e.dataIndex,!0);isNaN(a)||this._showIndicator(a,a)}}},_hideIndicator:function(){var t=this._shapes;t.indicator&&t.indicator.attr("invisible",!0),t.indicatorLabel&&t.indicatorLabel.attr("invisible",!0)},_clearHoverLinkToSeries:function(){this._hideIndicator();var t=this._hoverLinkDataIndices;this._dispatchHighDown("downplay",ex(t)),t.length=0},_clearHoverLinkFromSeries:function(){this._hideIndicator();var t=this.api.getZr();t.off("mouseover",this._hoverLinkFromSeriesMouseOver),t.off("mouseout",this._hideIndicator)},_applyTransform:function(t,e,i,n){var o=Ao(e,n?null:this.group);return zM[y(t)?"applyTransform":"transformDirection"](t,o,i)},_dispatchHighDown:function(t,e){e&&e.length&&this.api.dispatchAction({type:t,batch:e})},dispose:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()},remove:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()}});Es({type:"selectDataRange",event:"dataRangeSelected",update:"update"},function(t,e){e.eachComponent({mainType:"visualMap",query:t},function(e){e.setSelected(t.selected)})}),Ns(xO);var FO=LO.extend({type:"visualMap.piecewise",defaultOption:{selected:null,minOpen:!1,maxOpen:!1,align:"auto",itemWidth:20,itemHeight:14,itemSymbol:"roundRect",pieceList:null,categories:null,splitNumber:5,selectedMode:"multiple",itemGap:10,hoverLink:!0,showLabel:null},optionUpdated:function(t,e){FO.superApply(this,"optionUpdated",arguments),this._pieceList=[],this.resetExtent();var n=this._mode=this._determineMode();WO[this._mode].call(this),this._resetSelected(t,e);var o=this.option.categories;this.resetVisual(function(t,e){"categories"===n?(t.mappingMethod="category",t.categories=i(o)):(t.dataExtent=this.getExtent(),t.mappingMethod="piecewise",t.pieceList=f(this._pieceList,function(t){var t=i(t);return"inRange"!==e&&(t.visual=null),t}))})},completeVisualOption:function(){function t(t,e,i){return t&&t[e]&&(w(t[e])?t[e].hasOwnProperty(i):t[e]===i)}var e=this.option,i={},n=hL.listVisualTypes(),o=this.isCategory();d(e.pieces,function(t){d(n,function(e){t.hasOwnProperty(e)&&(i[e]=1)})}),d(i,function(i,n){var a=0;d(this.stateList,function(i){a|=t(e,i,n)||t(e.target,i,n)},this),!a&&d(this.stateList,function(t){(e[t]||(e[t]={}))[n]=wO.get(n,"inRange"===t?"active":"inactive",o)})},this),LO.prototype.completeVisualOption.apply(this,arguments)},_resetSelected:function(t,e){var i=this.option,n=this._pieceList,o=(e?i:t).selected||{};if(i.selected=o,d(n,function(t,e){var i=this.getSelectedMapKey(t);o.hasOwnProperty(i)||(o[i]=!0)},this),"single"===i.selectedMode){var a=!1;d(n,function(t,e){var i=this.getSelectedMapKey(t);o[i]&&(a?o[i]=!1:a=!0)},this)}},getSelectedMapKey:function(t){return"categories"===this._mode?t.value+"":t.index+""},getPieceList:function(){return this._pieceList},_determineMode:function(){var t=this.option;return t.pieces&&t.pieces.length>0?"pieces":this.option.categories?"categories":"splitNumber"},setSelected:function(t){this.option.selected=i(t)},getValueState:function(t){var e=hL.findPieceIndex(t,this._pieceList);return null!=e&&this.option.selected[this.getSelectedMapKey(this._pieceList[e])]?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){hL.findPieceIndex(e,this._pieceList)===t&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getRepresentValue:function(t){var e;if(this.isCategory())e=t.value;else if(null!=t.value)e=t.value;else{var i=t.interval||[];e=i[0]===-1/0&&i[1]===1/0?0:(i[0]+i[1])/2}return e},getVisualMeta:function(t){function e(e,a){var r=o.getRepresentValue({interval:e});a||(a=o.getValueState(r));var s=t(r,a);e[0]===-1/0?n[0]=s:e[1]===1/0?n[1]=s:i.push({value:e[0],color:s},{value:e[1],color:s})}if(!this.isCategory()){var i=[],n=[],o=this,a=this._pieceList.slice();if(a.length){var r=a[0].interval[0];r!==-1/0&&a.unshift({interval:[-1/0,r]}),(r=a[a.length-1].interval[1])!==1/0&&a.push({interval:[r,1/0]})}else a.push({interval:[-1/0,1/0]});var s=-1/0;return d(a,function(t){var i=t.interval;i&&(i[0]>s&&e([s,i[0]],"outOfRange"),e(i.slice()),s=i[1])},this),{stops:i,outerColors:n}}}}),WO={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i);var r=0;t.minOpen&&e.push({index:r++,interval:[-1/0,n[0]],close:[0,0]});for(var s=n[0],l=r+o;r","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};NO.extend({type:"visualMap.piecewise",doRender:function(){var t=this.group;t.removeAll();var e=this.visualMapModel,i=e.get("textGap"),n=e.textStyleModel,o=n.getFont(),a=n.getTextColor(),r=this._getItemAlign(),s=e.itemSize,l=this._getViewData(),u=l.endsText,h=T(e.get("showLabel",!0),!u);u&&this._renderEndsText(t,u[0],s,h,r),d(l.viewPieceList,function(n){var l=n.piece,u=new tb;u.onclick=m(this._onItemClick,this,l),this._enableHoverLink(u,n.indexInModelPieceList);var c=e.getRepresentValue(l);if(this._createItemSymbol(u,c,[0,0,s[0],s[1]]),h){var d=this.visualMapModel.getValueState(c);u.add(new rM({style:{x:"right"===r?-i:s[0]+i,y:s[1]/2,text:l.text,textVerticalAlign:"middle",textAlign:r,textFont:o,textFill:a,opacity:"outOfRange"===d?.5:1}}))}t.add(u)},this),u&&this._renderEndsText(t,u[1],s,h,r),aI(e.get("orient"),t,e.get("itemGap")),this.renderBackground(t),this.positionGroup(t)},_enableHoverLink:function(t,e){function i(t){var i=this.visualMapModel;i.option.hoverLink&&this.api.dispatchAction({type:t,batch:ex(i.findTargetDataIndices(e))})}t.on("mouseover",m(i,this,"highlight")).on("mouseout",m(i,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return tx(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new tb,r=this.visualMapModel.textStyleModel;a.add(new rM({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=f(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i&&(i=i.slice().reverse()),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(Jl(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,n=e.option,o=i(n.selected),a=e.getSelectedMapKey(t);"single"===n.selectedMode?(o[a]=!0,d(o,function(t,e){o[e]=e===a})):o[a]=!o[a],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:o})}});Ns(xO);var HO=ta,ZO=ia,UO=Fs({type:"marker",dependencies:["series","grid","polar","geo"],init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i),this.mergeOption(t,i,n.createdBySelf,!0)},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.__hostSeries;return this.getShallow("animation")&&t&&t.isAnimationEnabled()},mergeOption:function(t,e,i,n){var o=this.constructor,r=this.mainType+"Model";i||e.eachSeries(function(t){var i=t.get(this.mainType,!0),s=t[r];i&&i.data?(s?s.mergeOption(i,e,!0):(n&&ux(i),d(i.data,function(t){t instanceof Array?(ux(t[0]),ux(t[1])):ux(t)}),a(s=new o(i,this,e),{mainType:this.mainType,seriesIndex:t.seriesIndex,name:t.name,createdBySelf:!0}),s.__hostSeries=t),t[r]=s):t[r]=null},this)},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=y(i)?f(i,HO).join(", "):HO(i),o=e.getName(t),a=ZO(this.name);return(null!=i||o)&&(a+="
"),o&&(a+=ZO(o),null!=i&&(a+=" : ")),null!=i&&(a+=ZO(n)),a},getData:function(){return this._data},setData:function(t){this._data=t}});h(UO,ZI),UO.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var XO=l,jO=v,YO={min:jO(dx,"min"),max:jO(dx,"max"),average:jO(dx,"average")},qO=Ws({type:"marker",init:function(){this.markerGroupMap=R()},render:function(t,e,i){var n=this.markerGroupMap;n.each(function(t){t.__keep=!1});var o=this.type+"Model";e.eachSeries(function(t){var n=t[o];n&&this.renderSeries(t,n,e,i)},this),n.each(function(t){!t.__keep&&this.group.remove(t.group)},this)},renderSeries:function(){}});qO.extend({type:"markPoint",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markPointModel;e&&(xx(e.getData(),t,i),this.markerGroupMap.get(t.id).updateLayout(e))},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,r=t.getData(),s=this.markerGroupMap,l=s.get(a)||s.set(a,new Du),u=_x(o,t,e);e.setData(u),xx(e.getData(),t,n),u.each(function(t){var i=u.getItemModel(t),n=i.getShallow("symbolSize");"function"==typeof n&&(n=n(e.getRawValue(t),e.getDataParams(t))),u.setItemVisual(t,{symbolSize:n,color:i.get("itemStyle.color")||r.getVisual("color"),symbol:i.getShallow("symbol")})}),l.updateData(u),this.group.add(l.group),u.eachItemGraphicEl(function(t){t.traverse(function(t){t.dataModel=e})}),l.__keep=!0,l.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markPoint=t.markPoint||{}}),UO.extend({type:"markLine",defaultOption:{zlevel:0,z:5,symbol:["circle","arrow"],symbolSize:[8,16],precision:2,tooltip:{trigger:"item"},label:{show:!0,position:"end"},lineStyle:{type:"dashed"},emphasis:{label:{show:!0},lineStyle:{width:3}},animationEasing:"linear"}});var KO=function(t,e,o,r){var s=t.getData(),l=r.type;if(!y(r)&&("min"===l||"max"===l||"average"===l||"median"===l||null!=r.xAxis||null!=r.yAxis)){var u,h;if(null!=r.yAxis||null!=r.xAxis)u=null!=r.yAxis?"y":"x",e.getAxis(u),h=T(r.yAxis,r.xAxis);else{var c=px(r,s,e,t);u=c.valueDataDim,c.valueAxis,h=yx(s,u,l)}var d="x"===u?0:1,f=1-d,p=i(r),g={};p.type=null,p.coord=[],g.coord=[],p.coord[f]=-1/0,g.coord[f]=1/0;var m=o.get("precision");m>=0&&"number"==typeof h&&(h=+h.toFixed(Math.min(m,20))),p.coord[d]=g.coord[d]=h,r=[p,g,{type:l,valueIndex:r.valueIndex,value:h}]}return r=[fx(t,r[0]),fx(t,r[1]),a({},r[2])],r[2].type=r[2].type||"",n(r[2],r[0]),n(r[2],r[1]),r};qO.extend({type:"markLine",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markLineModel;if(e){var n=e.getData(),o=e.__from,a=e.__to;o.each(function(e){Ix(o,e,!0,t,i),Ix(a,e,!1,t,i)}),n.each(function(t){n.setItemLayout(t,[o.getItemLayout(t),a.getItemLayout(t)])}),this.markerGroupMap.get(t.id).updateLayout()}},this)},renderSeries:function(t,e,i,n){function o(e,i,o){var a=e.getItemModel(i);Ix(e,i,o,t,n),e.setItemVisual(i,{symbolSize:a.get("symbolSize")||g[o?0:1],symbol:a.get("symbol",!0)||p[o?0:1],color:a.get("itemStyle.color")||s.getVisual("color")})}var a=t.coordinateSystem,r=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(r)||l.set(r,new sf);this.group.add(u.group);var h=Tx(a,t,e),c=h.from,d=h.to,f=h.line;e.__from=c,e.__to=d,e.setData(f);var p=e.get("symbol"),g=e.get("symbolSize");y(p)||(p=[p,p]),"number"==typeof g&&(g=[g,g]),h.from.each(function(t){o(c,t,!0),o(d,t,!1)}),f.each(function(t){var e=f.getItemModel(t).get("lineStyle.color");f.setItemVisual(t,{color:e||c.getItemVisual(t,"color")}),f.setItemLayout(t,[c.getItemLayout(t),d.getItemLayout(t)]),f.setItemVisual(t,{fromSymbolSize:c.getItemVisual(t,"symbolSize"),fromSymbol:c.getItemVisual(t,"symbol"),toSymbolSize:d.getItemVisual(t,"symbolSize"),toSymbol:d.getItemVisual(t,"symbol")})}),u.updateData(f),h.line.eachItemGraphicEl(function(t,i){t.traverse(function(t){t.dataModel=e})}),u.__keep=!0,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markLine=t.markLine||{}}),UO.extend({type:"markArea",defaultOption:{zlevel:0,z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}}});var $O=function(t,e,i,n){var a=fx(t,n[0]),r=fx(t,n[1]),s=T,l=a.coord,u=r.coord;l[0]=s(l[0],-1/0),l[1]=s(l[1],-1/0),u[0]=s(u[0],1/0),u[1]=s(u[1],1/0);var h=o([{},a,r]);return h.coord=[a.coord,r.coord],h.x0=a.x,h.y0=a.y,h.x1=r.x,h.y1=r.y,h},JO=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]];qO.extend({type:"markArea",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markAreaModel;if(e){var n=e.getData();n.each(function(e){var o=f(JO,function(o){return Lx(n,e,o,t,i)});n.setItemLayout(e,o),n.getItemGraphicEl(e).setShape("points",o)})}},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(a)||l.set(a,{group:new tb});this.group.add(u.group),u.__keep=!0;var h=kx(o,t,e);e.setData(h),h.each(function(e){h.setItemLayout(e,f(JO,function(i){return Lx(h,e,i,t,n)})),h.setItemVisual(e,{color:s.getVisual("color")})}),h.diff(u.__data).add(function(t){var e=new pM({shape:{points:h.getItemLayout(t)}});h.setItemGraphicEl(t,e),u.group.add(e)}).update(function(t,i){var n=u.__data.getItemGraphicEl(i);Io(n,{shape:{points:h.getItemLayout(t)}},e,t),u.group.add(n),h.setItemGraphicEl(t,n)}).remove(function(t){var e=u.__data.getItemGraphicEl(t);u.group.remove(e)}).execute(),h.eachItemGraphicEl(function(t,i){var n=h.getItemModel(i),o=n.getModel("label"),a=n.getModel("emphasis.label"),s=h.getItemVisual(i,"color");t.useStyle(r(n.getModel("itemStyle").getItemStyle(),{fill:Yt(s,.4),stroke:s})),t.hoverStyle=n.getModel("emphasis.itemStyle").getItemStyle(),go(t.style,t.hoverStyle,o,a,{labelFetcher:e,labelDataIndex:i,defaultText:h.getName(i)||"",isRectText:!0,autoColor:s}),fo(t,{}),t.dataModel=e}),u.__data=h,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markArea=t.markArea||{}});lI.registerSubTypeDefaulter("timeline",function(){return"slider"}),Es({type:"timelineChange",event:"timelineChanged",update:"prepareAndUpdate"},function(t,e){var i=e.getComponent("timeline");return i&&null!=t.currentIndex&&(i.setCurrentIndex(t.currentIndex),!i.get("loop",!0)&&i.isIndexMax()&&i.setPlayState(!1)),e.resetOption("timeline"),r({currentIndex:i.option.currentIndex},t)}),Es({type:"timelinePlayChange",event:"timelinePlayChanged",update:"update"},function(t,e){var i=e.getComponent("timeline");i&&null!=t.playState&&i.setPlayState(t.playState)});var QO=lI.extend({type:"timeline",layoutMode:"box",defaultOption:{zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},init:function(t,e,i){this._data,this._names,this.mergeDefaultAndTheme(t,i),this._initData()},mergeOption:function(t){QO.superApply(this,"mergeOption",arguments),this._initData()},setCurrentIndex:function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(t>=e&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},getCurrentIndex:function(){return this.option.currentIndex},isIndexMax:function(){return this.getCurrentIndex()>=this._data.count()-1},setPlayState:function(t){this.option.autoPlay=!!t},getPlayState:function(){return!!this.option.autoPlay},_initData:function(){var t=this.option,e=t.data||[],n=t.axisType,o=this._names=[];if("category"===n){var a=[];d(e,function(t,e){var n,r=Li(t);w(t)?(n=i(t)).value=e:n=e,a.push(n),_(r)||null!=r&&!isNaN(r)||(r=""),o.push(r+"")}),e=a}var r={category:"ordinal",time:"time"}[n]||"number";(this._data=new vA([{name:"value",type:r}],this)).initData(e,o)},getData:function(){return this._data},getCategories:function(){if("category"===this.get("axisType"))return this._names.slice()}});h(QO.extend({type:"timeline.slider",defaultOption:{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"emptyCircle",symbolSize:10,lineStyle:{show:!0,width:2,color:"#304654"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#304654"},itemStyle:{color:"#304654",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:13,color:"#c23531",borderWidth:5,borderColor:"rgba(194,53,49, 0.5)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:22,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z",prevIcon:"path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z",color:"#304654",borderColor:"#304654",borderWidth:1},emphasis:{label:{show:!0,color:"#c23531"},itemStyle:{color:"#c23531"},controlStyle:{color:"#c23531",borderColor:"#c23531",borderWidth:2}},data:[]}}),ZI);var tE=qI.extend({type:"timeline"}),eE=function(t,e,i,n){aD.call(this,t,e,i),this.type=n||"value",this.model=null};eE.prototype={constructor:eE,getLabelModel:function(){return this.model.getModel("label")},isHorizontal:function(){return"horizontal"===this.model.get("orient")}},u(eE,aD);var iE=m,nE=d,oE=Math.PI;tE.extend({type:"timeline.slider",init:function(t,e){this.api=e,this._axis,this._viewRect,this._timer,this._currentPointer,this._mainGroup,this._labelGroup},render:function(t,e,i,n){if(this.model=t,this.api=i,this.ecModel=e,this.group.removeAll(),t.get("show",!0)){var o=this._layout(t,i),a=this._createGroup("mainGroup"),r=this._createGroup("labelGroup"),s=this._axis=this._createAxis(o,t);t.formatTooltip=function(t){return ia(s.scale.getLabel(t))},nE(["AxisLine","AxisTick","Control","CurrentPointer"],function(e){this["_render"+e](o,a,s,t)},this),this._renderAxisLabel(o,r,s,t),this._position(o,t)}this._doPlayStop()},remove:function(){this._clearTimer(),this.group.removeAll()},dispose:function(){this._clearTimer()},_layout:function(t,e){var i=t.get("label.position"),n=t.get("orient"),o=Ex(t,e);null==i||"auto"===i?i="horizontal"===n?o.y+o.height/2=0||"+"===i?"left":"right"},r={horizontal:i>=0||"+"===i?"top":"bottom",vertical:"middle"},s={horizontal:0,vertical:oE/2},l="vertical"===n?o.height:o.width,u=t.getModel("controlStyle"),h=u.get("show",!0),c=h?u.get("itemSize"):0,d=h?u.get("itemGap"):0,f=c+d,p=t.get("label.rotate")||0;p=p*oE/180;var g,m,v,y,x=u.get("position",!0),_=h&&u.get("showPlayBtn",!0),w=h&&u.get("showPrevBtn",!0),b=h&&u.get("showNextBtn",!0),S=0,M=l;return"left"===x||"bottom"===x?(_&&(g=[0,0],S+=f),w&&(m=[S,0],S+=f),b&&(v=[M-c,0],M-=f)):(_&&(g=[M-c,0],M-=f),w&&(m=[0,0],S+=f),b&&(v=[M-c,0],M-=f)),y=[S,M],t.get("inverse")&&y.reverse(),{viewRect:o,mainLength:l,orient:n,rotation:s[n],labelRotation:p,labelPosOpt:i,labelAlign:t.get("label.align")||a[n],labelBaseline:t.get("label.verticalAlign")||t.get("label.baseline")||r[n],playPosition:g,prevBtnPosition:m,nextBtnPosition:v,axisExtent:y,controlSize:c,controlGap:d}},_position:function(t,e){function i(t){var e=t.position;t.origin=[c[0][0]-e[0],c[1][0]-e[1]]}function n(t){return[[t.x,t.x+t.width],[t.y,t.y+t.height]]}function o(t,e,i,n,o){t[n]+=i[n][o]-e[n][o]}var a=this._mainGroup,r=this._labelGroup,s=t.viewRect;if("vertical"===t.orient){var l=xt(),u=s.x,h=s.y+s.height;St(l,l,[-u,-h]),Mt(l,l,-oE/2),St(l,l,[u,h]),(s=s.clone()).applyTransform(l)}var c=n(s),d=n(a.getBoundingRect()),f=n(r.getBoundingRect()),p=a.position,g=r.position;g[0]=p[0]=c[0][0];var m=t.labelPosOpt;if(isNaN(m))o(p,d,c,1,v="+"===m?0:1),o(g,f,c,1,1-v);else{var v=m>=0?0:1;o(p,d,c,1,v),g[1]=p[1]+m}a.attr("position",p),r.attr("position",g),a.rotation=r.rotation=t.rotation,i(a),i(r)},_createAxis:function(t,e){var i=e.getData(),n=e.get("axisType"),o=Hl(e,n);o.getTicks=function(){return i.mapArray(["value"],function(t){return t})};var a=i.getDataExtent("value");o.setExtent(a[0],a[1]),o.niceTicks();var r=new eE("value",o,t.axisExtent,n);return r.model=e,r},_createGroup:function(t){var e=this["_"+t]=new tb;return this.group.add(e),e},_renderAxisLine:function(t,e,i,n){var o=i.getExtent();n.get("lineStyle.show")&&e.add(new _M({shape:{x1:o[0],y1:0,x2:o[1],y2:0},style:a({lineCap:"round"},n.getModel("lineStyle").getLineStyle()),silent:!0,z2:1}))},_renderAxisTick:function(t,e,i,n){var o=n.getData(),a=i.scale.getTicks();nE(a,function(t){var a=i.dataToCoord(t),r=o.getItemModel(t),s=r.getModel("itemStyle"),l=r.getModel("emphasis.itemStyle"),u={position:[a,0],onclick:iE(this._changeTimeline,this,t)},h=zx(r,s,e,u);fo(h,l.getItemStyle()),r.get("tooltip")?(h.dataIndex=t,h.dataModel=n):h.dataIndex=h.dataModel=null},this)},_renderAxisLabel:function(t,e,i,n){if(i.getLabelModel().get("show")){var o=n.getData(),a=i.getViewLabels();nE(a,function(n){var a=n.tickValue,r=o.getItemModel(a),s=r.getModel("label"),l=r.getModel("emphasis.label"),u=i.dataToCoord(n.tickValue),h=new rM({position:[u,0],rotation:t.labelRotation-t.rotation,onclick:iE(this._changeTimeline,this,a),silent:!1});mo(h.style,s,{text:n.formattedLabel,textAlign:t.labelAlign,textVerticalAlign:t.labelBaseline}),e.add(h),fo(h,mo({},l))},this)}},_renderControl:function(t,e,i,n){function o(t,i,o,h){if(t){var c=Rx(n,i,u,{position:t,origin:[a/2,0],rotation:h?-r:0,rectHover:!0,style:s,onclick:o});e.add(c),fo(c,l)}}var a=t.controlSize,r=t.rotation,s=n.getModel("controlStyle").getItemStyle(),l=n.getModel("emphasis.controlStyle").getItemStyle(),u=[0,-a/2,a,a],h=n.getPlayState(),c=n.get("inverse",!0);o(t.nextBtnPosition,"controlStyle.nextIcon",iE(this._changeTimeline,this,c?"-":"+")),o(t.prevBtnPosition,"controlStyle.prevIcon",iE(this._changeTimeline,this,c?"+":"-")),o(t.playPosition,"controlStyle."+(h?"stopIcon":"playIcon"),iE(this._handlePlayClick,this,!h),!0)},_renderCurrentPointer:function(t,e,i,n){var o=n.getData(),a=n.getCurrentIndex(),r=o.getItemModel(a).getModel("checkpointStyle"),s=this,l={onCreate:function(t){t.draggable=!0,t.drift=iE(s._handlePointerDrag,s),t.ondragend=iE(s._handlePointerDragend,s),Bx(t,a,i,n,!0)},onUpdate:function(t){Bx(t,a,i,n)}};this._currentPointer=zx(r,r,this._mainGroup,{},this._currentPointer,l)},_handlePlayClick:function(t){this._clearTimer(),this.api.dispatchAction({type:"timelinePlayChange",playState:t,from:this.uid})},_handlePointerDrag:function(t,e,i){this._clearTimer(),this._pointerChangeTimeline([i.offsetX,i.offsetY])},_handlePointerDragend:function(t){this._pointerChangeTimeline([t.offsetX,t.offsetY],!0)},_pointerChangeTimeline:function(t,e){var i=this._toAxisCoord(t)[0],n=Fo(this._axis.getExtent().slice());i>n[1]&&(i=n[1]),ii.getHeight()&&(n.textPosition="top",l=!0);var u=l?-5-o.height:s+8;a+o.width/2>i.getWidth()?(n.textPosition=["100%",u],n.textAlign="right"):a-o.width/2<0&&(n.textPosition=[0,u],n.textAlign="left")}})}},updateView:function(t,e,i,n){d(this._features,function(t){t.updateView&&t.updateView(t.model,e,i,n)})},remove:function(t,e){d(this._features,function(i){i.remove&&i.remove(t,e)}),this.group.removeAll()},dispose:function(t,e){d(this._features,function(i){i.dispose&&i.dispose(t,e)})}});var rE=rT.toolbox.saveAsImage;Gx.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:rE.title,type:"png",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:rE.lang.slice()},Gx.prototype.unusable=!U_.canvasSupported,Gx.prototype.onclick=function(t,e){var i=this.model,n=i.get("name")||t.get("title.0.text")||"echarts",o=document.createElement("a"),a=i.get("type",!0)||"png";o.download=n+"."+a,o.target="_blank";var r=e.getConnectedDataURL({type:a,backgroundColor:i.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",excludeComponents:i.get("excludeComponents"),pixelRatio:i.get("pixelRatio")});if(o.href=r,"function"!=typeof MouseEvent||U_.browser.ie||U_.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var s=atob(r.split(",")[1]),l=s.length,u=new Uint8Array(l);l--;)u[l]=s.charCodeAt(l);var h=new Blob([u]);window.navigator.msSaveOrOpenBlob(h,n+"."+a)}else{var c=i.get("lang"),d='';window.open().document.write(d)}else{var f=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});o.dispatchEvent(f)}},Ty("saveAsImage",Gx);var sE=rT.toolbox.magicType;Fx.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z",tiled:"M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z"},title:i(sE.title),option:{},seriesIndex:{}};var lE=Fx.prototype;lE.getIcons=function(){var t=this.model,e=t.get("icon"),i={};return d(t.get("type"),function(t){e[t]&&(i[t]=e[t])}),i};var uE={line:function(t,e,i,o){if("bar"===t)return n({id:e,type:"line",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.line")||{},!0)},bar:function(t,e,i,o){if("line"===t)return n({id:e,type:"bar",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.bar")||{},!0)},stack:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:"__ec_magicType_stack__"},o.get("option.stack")||{},!0)},tiled:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:""},o.get("option.tiled")||{},!0)}},hE=[["line","bar"],["stack","tiled"]];lE.onclick=function(t,e,i){var n=this.model,o=n.get("seriesIndex."+i);if(uE[i]){var a={series:[]};d(hE,function(t){l(t,i)>=0&&d(t,function(t){n.setIconStatus(t,"normal")})}),n.setIconStatus(i,"emphasis"),t.eachComponent({mainType:"series",query:null==o?null:{seriesIndex:o}},function(e){var o=e.subType,s=e.id,l=uE[i](o,s,e,n);l&&(r(l,e.option),a.series.push(l));var u=e.coordinateSystem;if(u&&"cartesian2d"===u.type&&("line"===i||"bar"===i)){var h=u.getAxesByScale("ordinal")[0];if(h){var c=h.dim+"Axis",d=t.queryComponents({mainType:c,index:e.get(name+"Index"),id:e.get(name+"Id")})[0].componentIndex;a[c]=a[c]||[];for(var f=0;f<=d;f++)a[c][d]=a[c][d]||{};a[c][d].boundaryGap="bar"===i}}}),e.dispatchAction({type:"changeMagicType",currentType:i,newOption:a})}},Es({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),Ty("magicType",Fx);var cE=rT.toolbox.dataView,dE=new Array(60).join("-"),fE="\t",pE=new RegExp("["+fE+"]+","g");$x.defaultOption={show:!0,readOnly:!1,optionToContent:null,contentToOption:null,icon:"M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28",title:i(cE.title),lang:i(cE.lang),backgroundColor:"#fff",textColor:"#000",textareaColor:"#fff",textareaBorderColor:"#333",buttonColor:"#c23531",buttonTextColor:"#fff"},$x.prototype.onclick=function(t,e){function i(){n.removeChild(a),x._dom=null}var n=e.getDom(),o=this.model;this._dom&&n.removeChild(this._dom);var a=document.createElement("div");a.style.cssText="position:absolute;left:5px;top:5px;bottom:5px;right:5px;",a.style.backgroundColor=o.get("backgroundColor")||"#fff";var r=document.createElement("h4"),s=o.get("lang")||[];r.innerHTML=s[0]||o.get("title"),r.style.cssText="margin: 10px 20px;",r.style.color=o.get("textColor");var l=document.createElement("div"),u=document.createElement("textarea");l.style.cssText="display:block;width:100%;overflow:auto;";var h=o.get("optionToContent"),c=o.get("contentToOption"),d=Ux(t);if("function"==typeof h){var f=h(e.getOption());"string"==typeof f?l.innerHTML=f:M(f)&&l.appendChild(f)}else l.appendChild(u),u.readOnly=o.get("readOnly"),u.style.cssText="width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;",u.style.color=o.get("textColor"),u.style.borderColor=o.get("textareaBorderColor"),u.style.backgroundColor=o.get("textareaColor"),u.value=d.value;var p=d.meta,g=document.createElement("div");g.style.cssText="position:absolute;bottom:0;left:0;right:0;";var m="float:right;margin-right:20px;border:none;cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px",v=document.createElement("div"),y=document.createElement("div");m+=";background-color:"+o.get("buttonColor"),m+=";color:"+o.get("buttonTextColor");var x=this;ht(v,"click",i),ht(y,"click",function(){var t;try{t="function"==typeof c?c(l,e.getOption()):Kx(u.value,p)}catch(t){throw i(),new Error("Data view format error "+t)}t&&e.dispatchAction({type:"changeDataView",newOption:t}),i()}),v.innerHTML=s[1],y.innerHTML=s[2],y.style.cssText=m,v.style.cssText=m,!o.get("readOnly")&&g.appendChild(y),g.appendChild(v),ht(u,"keydown",function(t){if(9===(t.keyCode||t.which)){var e=this.value,i=this.selectionStart,n=this.selectionEnd;this.value=e.substring(0,i)+fE+e.substring(n),this.selectionStart=this.selectionEnd=i+1,mw(t)}}),a.appendChild(r),a.appendChild(l),a.appendChild(g),l.style.height=n.clientHeight-80+"px",n.appendChild(a),this._dom=a},$x.prototype.remove=function(t,e){this._dom&&e.getDom().removeChild(this._dom)},$x.prototype.dispose=function(t,e){this.remove(t,e)},Ty("dataView",$x),Es({type:"changeDataView",event:"dataViewChanged",update:"prepareAndUpdate"},function(t,e){var i=[];d(t.newOption.series,function(t){var n=e.getSeriesByName(t.name)[0];if(n){var o=n.get("data");i.push({name:t.name,data:Jx(t.data,o)})}else i.push(a({type:"scatter"},t))}),e.mergeOption(r({series:i},t.newOption))});var gE=d,mE="\0_ec_hist_store";iO.extend({type:"dataZoom.select"}),nO.extend({type:"dataZoom.select"});var vE=rT.toolbox.dataZoom,yE=d,xE="\0_ec_\0toolbox-dataZoom_";o_.defaultOption={show:!0,icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:i(vE.title)};var _E=o_.prototype;_E.render=function(t,e,i,n){this.model=t,this.ecModel=e,this.api=i,s_(t,e,this,n,i),r_(t,e)},_E.onclick=function(t,e,i){wE[i].call(this)},_E.remove=function(t,e){this._brushController.unmount()},_E.dispose=function(t,e){this._brushController.dispose()};var wE={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(t_(this.ecModel))}};_E._onBrush=function(t,e){function i(t,e,i){var r=e.getAxis(t),s=r.model,l=n(t,s,a),u=l.findRepresentativeAxisProxy(s).getMinMaxSpan();null==u.minValueSpan&&null==u.maxValueSpan||(i=QL(0,i.slice(),r.scale.getExtent(),0,u.minValueSpan,u.maxValueSpan)),l&&(o[l.id]={dataZoomId:l.id,startValue:i[0],endValue:i[1]})}function n(t,e,i){var n;return i.eachComponent({mainType:"dataZoom",subType:"select"},function(i){i.getAxisModel(t,e.componentIndex)&&(n=i)}),n}if(e.isEnd&&t.length){var o={},a=this.ecModel;this._brushController.updateCovers([]),new hy(a_(this.model.option),a,{include:["grid"]}).matchOutputRanges(t,a,function(t,e,n){if("cartesian2d"===n.type){var o=t.brushType;"rect"===o?(i("x",n,e[0]),i("y",n,e[1])):i({lineX:"x",lineY:"y"}[o],n,e)}}),Qx(a,o),this._dispatchZoomAction(o)}},_E._dispatchZoomAction=function(t){var e=[];yE(t,function(t,n){e.push(i(t))}),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},Ty("dataZoom",o_),Ns(function(t){function e(t,e){if(e){var o=t+"Index",a=e[o];null==a||"all"===a||y(a)||(a=!1===a||"none"===a?[]:[a]),i(t,function(e,i){if(null==a||"all"===a||-1!==l(a,i)){var r={type:"select",$fromToolbox:!0,id:xE+t+i};r[o]=i,n.push(r)}})}}function i(e,i){var n=t[e];y(n)||(n=n?[n]:[]),yE(n,i)}if(t){var n=t.dataZoom||(t.dataZoom=[]);y(n)||(t.dataZoom=n=[n]);var o=t.toolbox;if(o&&(y(o)&&(o=o[0]),o&&o.feature)){var a=o.feature.dataZoom;e("xAxis",a),e("yAxis",a)}}});var bE=rT.toolbox.restore;l_.defaultOption={show:!0,icon:"M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5",title:bE.title},l_.prototype.onclick=function(t,e,i){e_(t),e.dispatchAction({type:"restore",from:this.uid})},Ty("restore",l_),Es({type:"restore",event:"restore",update:"prepareAndUpdate"},function(t,e){e.resetOption("recreate")});var SE,ME="urn:schemas-microsoft-com:vml",IE="undefined"==typeof window?null:window,TE=!1,AE=IE&&IE.document;if(AE&&!U_.canvasSupported)try{!AE.namespaces.zrvml&&AE.namespaces.add("zrvml",ME),SE=function(t){return AE.createElement("')}}catch(t){SE=function(t){return AE.createElement("<"+t+' xmlns="'+ME+'" class="zrvml">')}}var DE=ES.CMD,CE=Math.round,LE=Math.sqrt,kE=Math.abs,PE=Math.cos,NE=Math.sin,OE=Math.max;if(!U_.canvasSupported){var EE=21600,RE=EE/2,zE=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=EE+","+EE,t.coordorigin="0,0"},BE=function(t){return String(t).replace(/&/g,"&").replace(/"/g,""")},VE=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},GE=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},FE=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},WE=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},HE=function(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t},ZE=function(t,e,i){var n=Gt(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=VE(n[0],n[1],n[2]),t.opacity=i*n[3])},UE=function(t){var e=Gt(t);return[VE(e[0],e[1],e[2]),e[3]]},XE=function(t,e,i){var n=e.fill;if(null!=n)if(n instanceof IM){var o,a=0,r=[0,0],s=0,l=1,u=i.getBoundingRect(),h=u.width,c=u.height;if("linear"===n.type){o="gradient";var d=i.transform,f=[n.x*h,n.y*c],p=[n.x2*h,n.y2*c];d&&(Q(f,f,d),Q(p,p,d));var g=p[0]-f[0],m=p[1]-f[1];(a=180*Math.atan2(g,m)/Math.PI)<0&&(a+=360),a<1e-6&&(a=0)}else{o="gradientradial";var f=[n.x*h,n.y*c],d=i.transform,v=i.scale,y=h,x=c;r=[(f[0]-u.x)/y,(f[1]-u.y)/x],d&&Q(f,f,d),y/=v[0]*EE,x/=v[1]*EE;var _=OE(y,x);s=0/_,l=2*n.r/_-s}var w=n.colorStops.slice();w.sort(function(t,e){return t.offset-e.offset});for(var b=w.length,S=[],M=[],I=0;I=2){var D=S[0][0],C=S[1][0],L=S[0][1]*e.opacity,k=S[1][1]*e.opacity;t.type=o,t.method="none",t.focus="100%",t.angle=a,t.color=D,t.color2=C,t.colors=M.join(","),t.opacity=k,t.opacity2=L}"radial"===o&&(t.focusposition=r.join(","))}else ZE(t,n,e.opacity)},jE=function(t,e){null!=e.lineDash&&(t.dashstyle=e.lineDash.join(" ")),null==e.stroke||e.stroke instanceof IM||ZE(t,e.stroke,e.opacity)},YE=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof IM&&FE(t,a),a||(a=u_(e)),o?XE(a,i,n):jE(a,i),GE(t,a)):(t[o?"filled":"stroked"]="false",FE(t,a))},qE=[[],[],[]],KE=function(t,e){var i,n,o,a,r,s,l=DE.M,u=DE.C,h=DE.L,c=DE.A,d=DE.Q,f=[],p=t.data,g=t.len();for(a=0;a.01?N&&(O+=.0125):Math.abs(E-D)<1e-4?N&&OA?x-=.0125:x+=.0125:N&&ED?y+=.0125:y-=.0125),f.push(R,CE(((A-C)*M+b)*EE-RE),",",CE(((D-L)*I+S)*EE-RE),",",CE(((A+C)*M+b)*EE-RE),",",CE(((D+L)*I+S)*EE-RE),",",CE((O*M+b)*EE-RE),",",CE((E*I+S)*EE-RE),",",CE((y*M+b)*EE-RE),",",CE((x*I+S)*EE-RE)),r=y,s=x;break;case DE.R:var z=qE[0],B=qE[1];z[0]=p[a++],z[1]=p[a++],B[0]=z[0]+p[a++],B[1]=z[1]+p[a++],e&&(Q(z,z,e),Q(B,B,e)),z[0]=CE(z[0]*EE-RE),B[0]=CE(B[0]*EE-RE),z[1]=CE(z[1]*EE-RE),B[1]=CE(B[1]*EE-RE),f.push(" m ",z[0],",",z[1]," l ",B[0],",",z[1]," l ",B[0],",",B[1]," l ",z[0],",",B[1]);break;case DE.Z:f.push(" x ")}if(i>0){f.push(n);for(var V=0;V100&&(tR=0,QE={});var i,n=eR.style;try{n.font=t,i=n.fontFamily.split(",")[0]}catch(t){}e={style:n.fontStyle||"normal",variant:n.fontVariant||"normal",weight:n.fontWeight||"normal",size:0|parseFloat(n.fontSize||12),family:i||"Microsoft YaHei"},QE[t]=e,tR++}return e};!function(t,e){bb[t]=e}("measureText",function(t,e){var i=AE;JE||((JE=i.createElement("div")).style.cssText="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;",AE.body.appendChild(JE));try{JE.style.font=e}catch(t){}return JE.innerHTML="",JE.appendChild(i.createTextNode(t)),{width:JE.offsetWidth}});for(var nR=new de,oR=[Db,di,fi,Pn,rM],aR=0;aR=o&&u+1>=a){for(var h=[],c=0;c=o&&c+1>=a)return T_(0,s.components);l[i]=s}else l[i]=void 0}r++}();if(d)return d}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},D_.prototype.update=function(t,e){if(t){var i=this.getDefs(!1);if(t[this._domName]&&i.contains(t[this._domName]))"function"==typeof e&&e(t);else{var n=this.add(t);n&&(t[this._domName]=n)}}},D_.prototype.addDom=function(t){this.getDefs(!0).appendChild(t)},D_.prototype.removeDom=function(t){var e=this.getDefs(!1);e&&t[this._domName]&&(e.removeChild(t[this._domName]),t[this._domName]=null)},D_.prototype.getDoms=function(){var t=this.getDefs(!1);if(!t)return[];var e=[];return d(this._tagNames,function(i){var n=t.getElementsByTagName(i);e=e.concat([].slice.call(n))}),e},D_.prototype.markAllUnused=function(){var t=this;d(this.getDoms(),function(e){e[t._markLabel]="0"})},D_.prototype.markUsed=function(t){t&&(t[this._markLabel]="1")},D_.prototype.removeUnused=function(){var t=this.getDefs(!1);if(t){var e=this;d(this.getDoms(),function(i){"1"!==i[e._markLabel]&&t.removeChild(i)})}},D_.prototype.getSvgProxy=function(t){return t instanceof Pn?yR:t instanceof fi?xR:t instanceof rM?_R:yR},D_.prototype.getTextSvgElement=function(t){return t.__textSvgEl},D_.prototype.getSvgElement=function(t){return t.__svgEl},u(C_,D_),C_.prototype.addWithoutUpdate=function(t,e){if(e&&e.style){var i=this;d(["fill","stroke"],function(n){if(e.style[n]&&("linear"===e.style[n].type||"radial"===e.style[n].type)){var o,a=e.style[n],r=i.getDefs(!0);a._dom?(o=a._dom,r.contains(a._dom)||i.addDom(o)):o=i.add(a),i.markUsed(e);var s=o.getAttribute("id");t.setAttribute(n,"url(#"+s+")")}})}},C_.prototype.add=function(t){var e;if("linear"===t.type)e=this.createElement("linearGradient");else{if("radial"!==t.type)return Yw("Illegal gradient type."),null;e=this.createElement("radialGradient")}return t.id=t.id||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-gradient-"+t.id),this.updateDom(t,e),this.addDom(e),e},C_.prototype.update=function(t){var e=this;D_.prototype.update.call(this,t,function(){var i=t.type,n=t._dom.tagName;"linear"===i&&"linearGradient"===n||"radial"===i&&"radialGradient"===n?e.updateDom(t,t._dom):(e.removeDom(t),e.add(t))})},C_.prototype.updateDom=function(t,e){if("linear"===t.type)e.setAttribute("x1",t.x),e.setAttribute("y1",t.y),e.setAttribute("x2",t.x2),e.setAttribute("y2",t.y2);else{if("radial"!==t.type)return void Yw("Illegal gradient type.");e.setAttribute("cx",t.x),e.setAttribute("cy",t.y),e.setAttribute("r",t.r)}t.global?e.setAttribute("gradientUnits","userSpaceOnUse"):e.setAttribute("gradientUnits","objectBoundingBox"),e.innerHTML="";for(var i=t.colorStops,n=0,o=i.length;n0){var n,o,a=this.getDefs(!0),r=e[0],s=i?"_textDom":"_dom";r[s]?(o=r[s].getAttribute("id"),n=r[s],a.contains(n)||a.appendChild(n)):(o="zr"+this._zrId+"-clip-"+this.nextId,++this.nextId,(n=this.createElement("clipPath")).setAttribute("id",o),a.appendChild(n),r[s]=n);var l=this.getSvgProxy(r);if(r.transform&&r.parent.invTransform&&!i){var u=Array.prototype.slice.call(r.transform);bt(r.transform,r.parent.invTransform,r.transform),l.brush(r),r.transform=u}else l.brush(r);var h=this.getSvgElement(r);n.innerHTML="",n.appendChild(h.cloneNode()),t.setAttribute("clip-path","url(#"+o+")"),e.length>1&&this.updateDom(n,e.slice(1),i)}else t&&t.setAttribute("clip-path","none")},L_.prototype.markUsed=function(t){var e=this;t.__clipPaths&&t.__clipPaths.length>0&&d(t.__clipPaths,function(t){t._dom&&D_.prototype.markUsed.call(e,t._dom),t._textDom&&D_.prototype.markUsed.call(e,t._textDom)})},u(k_,D_),k_.prototype.addWithoutUpdate=function(t,e){if(e&&P_(e.style)){var i,n=e.style;n._shadowDom?(i=n._shadowDom,this.getDefs(!0).contains(n._shadowDom)||this.addDom(i)):i=this.add(e),this.markUsed(e);var o=i.getAttribute("id");t.style.filter="url(#"+o+")"}},k_.prototype.add=function(t){var e=this.createElement("filter"),i=t.style;return i._shadowDomId=i._shadowDomId||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-shadow-"+i._shadowDomId),this.updateDom(t,e),this.addDom(e),e},k_.prototype.update=function(t,e){var i=e.style;if(P_(i)){var n=this;D_.prototype.update.call(this,e,function(t){n.updateDom(e,t._shadowDom)})}else this.remove(t,i)},k_.prototype.remove=function(t,e){null!=e._shadowDomId&&(this.removeDom(e),t.style.filter="")},k_.prototype.updateDom=function(t,e){var i=e.getElementsByTagName("feDropShadow");i=0===i.length?this.createElement("feDropShadow"):i[0];var n,o,a,r,s=t.style,l=t.scale?t.scale[0]||1:1,u=t.scale?t.scale[1]||1:1;if(s.shadowBlur||s.shadowOffsetX||s.shadowOffsetY)n=s.shadowOffsetX||0,o=s.shadowOffsetY||0,a=s.shadowBlur,r=s.shadowColor;else{if(!s.textShadowBlur)return void this.removeDom(e,s);n=s.textShadowOffsetX||0,o=s.textShadowOffsetY||0,a=s.textShadowBlur,r=s.textShadowColor}i.setAttribute("dx",n/l),i.setAttribute("dy",o/u),i.setAttribute("flood-color",r);var h=a/2/l+" "+a/2/u;i.setAttribute("stdDeviation",h),e.setAttribute("x","-100%"),e.setAttribute("y","-100%"),e.setAttribute("width",Math.ceil(a/2*200)+"%"),e.setAttribute("height",Math.ceil(a/2*200)+"%"),e.appendChild(i),s._shadowDom=e},k_.prototype.markUsed=function(t){var e=t.style;e&&e._shadowDom&&D_.prototype.markUsed.call(this,e._shadowDom)};var IR=function(t,e,i,n){this.root=t,this.storage=e,this._opts=i=a({},i||{});var o=p_("svg");o.setAttribute("xmlns","http://www.w3.org/2000/svg"),o.setAttribute("version","1.1"),o.setAttribute("baseProfile","full"),o.style.cssText="user-select:none;position:absolute;left:0;top:0;",this.gradientManager=new C_(n,o),this.clipPathManager=new L_(n,o),this.shadowManager=new k_(n,o);var r=document.createElement("div");r.style.cssText="overflow:hidden;position:relative",this._svgRoot=o,this._viewport=r,t.appendChild(r),r.appendChild(o),this.resize(i.width,i.height),this._visibleList=[]};IR.prototype={constructor:IR,getType:function(){return"svg"},getViewportRoot:function(){return this._viewport},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(){var t=this.storage.getDisplayList(!0);this._paintList(t)},setBackgroundColor:function(t){this._viewport.style.background=t},_paintList:function(t){this.gradientManager.markAllUnused(),this.clipPathManager.markAllUnused(),this.shadowManager.markAllUnused();var e,i=this._svgRoot,n=this._visibleList,o=t.length,a=[];for(e=0;e=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},resize:function(t,e){var i=this._viewport;i.style.display="none";var n=this._opts;if(null!=t&&(n.width=t),null!=e&&(n.height=e),t=this._getSize(0),e=this._getSize(1),i.style.display="",this._width!==t||this._height!==e){this._width=t,this._height=e;var o=i.style;o.width=t+"px",o.height=e+"px";var a=this._svgRoot;a.setAttribute("width",t),a.setAttribute("height",e)}},getWidth:function(){return this._width},getHeight:function(){return this._height},_getSize:function(t){var e=this._opts,i=["width","height"][t],n=["clientWidth","clientHeight"][t],o=["paddingLeft","paddingTop"][t],a=["paddingRight","paddingBottom"][t];if(null!=e[i]&&"auto"!==e[i])return parseFloat(e[i]);var r=this.root,s=document.defaultView.getComputedStyle(r);return(r[n]||N_(s[i])||N_(r.style[i]))-(N_(s[o])||0)-(N_(s[a])||0)|0},dispose:function(){this.root.innerHTML="",this._svgRoot=this._viewport=this.storage=null},clear:function(){this._viewport&&this.root.removeChild(this._viewport)},pathToDataUrl:function(){return this.refresh(),"data:image/svg+xml;charset=UTF-8,"+this._svgRoot.outerHTML}},d(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","toDataURL","pathToImage"],function(t){IR.prototype[t]=F_(t)}),Ti("svg",IR),t.version="4.2.1",t.dependencies=ET,t.PRIORITY=VT,t.init=function(t,e,i){var n=ks(t);if(n)return n;var o=new us(t,e,i);return o.id="ec_"+iA++,tA[o.id]=o,Fi(t,oA,o.id),Cs(o),o},t.connect=function(t){if(y(t)){var e=t;t=null,kT(e,function(e){null!=e.group&&(t=e.group)}),t=t||"g_"+nA++,kT(e,function(e){e.group=t})}return eA[t]=!0,t},t.disConnect=Ls,t.disconnect=aA,t.dispose=function(t){"string"==typeof t?t=tA[t]:t instanceof us||(t=ks(t)),t instanceof us&&!t.isDisposed()&&t.dispose()},t.getInstanceByDom=ks,t.getInstanceById=function(t){return tA[t]},t.registerTheme=Ps,t.registerPreprocessor=Ns,t.registerProcessor=Os,t.registerPostUpdate=function(t){KT.push(t)},t.registerAction=Es,t.registerCoordinateSystem=Rs,t.getCoordinateSystemDimensions=function(t){var e=Fa.get(t);if(e)return e.getDimensionsInfo?e.getDimensionsInfo():e.dimensions.slice()},t.registerLayout=zs,t.registerVisual=Bs,t.registerLoading=Gs,t.extendComponentModel=Fs,t.extendComponentView=Ws,t.extendSeriesModel=Hs,t.extendChartView=Zs,t.setCanvasCreator=function(t){e("createCanvas",t)},t.registerMap=function(t,e,i){DT.registerMap(t,e,i)},t.getMap=function(t){var e=DT.retrieveMap(t);return e&&e[0]&&{geoJson:e[0].geoJSON,specialAreas:e[0].specialAreas}},t.dataTool=rA,t.zrender=Hb,t.number=YM,t.format=eI,t.throttle=Pr,t.helper=tD,t.matrix=Sw,t.vector=cw,t.color=Ww,t.parseGeoJSON=iD,t.parseGeoJson=rD,t.util=sD,t.graphic=lD,t.List=vA,t.Model=No,t.Axis=aD,t.env=U_}); \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/qiun-data-charts/static/h5/echarts.min.js b/yanzhu-ui-app/uni_modules/qiun-data-charts/static/h5/echarts.min.js new file mode 100644 index 00000000..5396a032 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/qiun-data-charts/static/h5/echarts.min.js @@ -0,0 +1,23 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +* 版本为4.2.1,修改一处源码:this.el.hide() 改为 this.el?this.el.hide():true +*/ + + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";function e(t,e){"createCanvas"===t&&(nw=null),ew[t]=e}function i(t){if(null==t||"object"!=typeof t)return t;var e=t,n=Y_.call(t);if("[object Array]"===n){if(!O(t)){e=[];for(var o=0,a=t.length;o=0){var o="touchend"!==n?e.targetTouches[0]:e.changedTouches[0];o&&st(t,o,e,i)}else st(t,e,e,i),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var a=e.button;return null==e.which&&void 0!==a&&gw.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function ht(t,e,i){pw?t.addEventListener(e,i):t.attachEvent("on"+e,i)}function ct(t,e,i){pw?t.removeEventListener(e,i):t.detachEvent("on"+e,i)}function dt(t){return 2===t.which||3===t.which}function ft(t){var e=t[1][0]-t[0][0],i=t[1][1]-t[0][1];return Math.sqrt(e*e+i*i)}function pt(t){return[(t[0][0]+t[1][0])/2,(t[0][1]+t[1][1])/2]}function gt(t,e,i){return{type:t,event:i,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:i.zrX,offsetY:i.zrY,gestureEvent:i.gestureEvent,pinchX:i.pinchX,pinchY:i.pinchY,pinchScale:i.pinchScale,wheelDelta:i.zrDelta,zrByTouch:i.zrByTouch,which:i.which,stop:mt}}function mt(t){mw(this.event)}function vt(){}function yt(t,e,i){if(t[t.rectHover?"rectContain":"contain"](e,i)){for(var n,o=t;o;){if(o.clipPath&&!o.clipPath.contain(e,i))return!1;o.silent&&(n=!0),o=o.parent}return!n||xw}return!1}function xt(){var t=new bw(6);return _t(t),t}function _t(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function wt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t}function bt(t,e,i){var n=e[0]*i[0]+e[2]*i[1],o=e[1]*i[0]+e[3]*i[1],a=e[0]*i[2]+e[2]*i[3],r=e[1]*i[2]+e[3]*i[3],s=e[0]*i[4]+e[2]*i[5]+e[4],l=e[1]*i[4]+e[3]*i[5]+e[5];return t[0]=n,t[1]=o,t[2]=a,t[3]=r,t[4]=s,t[5]=l,t}function St(t,e,i){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4]+i[0],t[5]=e[5]+i[1],t}function Mt(t,e,i){var n=e[0],o=e[2],a=e[4],r=e[1],s=e[3],l=e[5],u=Math.sin(i),h=Math.cos(i);return t[0]=n*h+r*u,t[1]=-n*u+r*h,t[2]=o*h+s*u,t[3]=-o*u+h*s,t[4]=h*a+u*l,t[5]=h*l-u*a,t}function It(t,e,i){var n=i[0],o=i[1];return t[0]=e[0]*n,t[1]=e[1]*o,t[2]=e[2]*n,t[3]=e[3]*o,t[4]=e[4]*n,t[5]=e[5]*o,t}function Tt(t,e){var i=e[0],n=e[2],o=e[4],a=e[1],r=e[3],s=e[5],l=i*r-a*n;return l?(l=1/l,t[0]=r*l,t[1]=-a*l,t[2]=-n*l,t[3]=i*l,t[4]=(n*s-r*o)*l,t[5]=(a*o-i*s)*l,t):null}function At(t){var e=xt();return wt(e,t),e}function Dt(t){return t>Iw||t<-Iw}function Ct(t){this._target=t.target,this._life=t.life||1e3,this._delay=t.delay||0,this._initialized=!1,this.loop=null!=t.loop&&t.loop,this.gap=t.gap||0,this.easing=t.easing||"Linear",this.onframe=t.onframe,this.ondestroy=t.ondestroy,this.onrestart=t.onrestart,this._pausedTime=0,this._paused=!1}function Lt(t){return(t=Math.round(t))<0?0:t>255?255:t}function kt(t){return(t=Math.round(t))<0?0:t>360?360:t}function Pt(t){return t<0?0:t>1?1:t}function Nt(t){return Lt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100*255:parseInt(t,10))}function Ot(t){return Pt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100:parseFloat(t))}function Et(t,e,i){return i<0?i+=1:i>1&&(i-=1),6*i<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}function Rt(t,e,i){return t+(e-t)*i}function zt(t,e,i,n,o){return t[0]=e,t[1]=i,t[2]=n,t[3]=o,t}function Bt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}function Vt(t,e){Vw&&Bt(Vw,e),Vw=Bw.put(t,Vw||e.slice())}function Gt(t,e){if(t){e=e||[];var i=Bw.get(t);if(i)return Bt(e,i);var n=(t+="").replace(/ /g,"").toLowerCase();if(n in zw)return Bt(e,zw[n]),Vt(t,e),e;if("#"!==n.charAt(0)){var o=n.indexOf("("),a=n.indexOf(")");if(-1!==o&&a+1===n.length){var r=n.substr(0,o),s=n.substr(o+1,a-(o+1)).split(","),l=1;switch(r){case"rgba":if(4!==s.length)return void zt(e,0,0,0,1);l=Ot(s.pop());case"rgb":return 3!==s.length?void zt(e,0,0,0,1):(zt(e,Nt(s[0]),Nt(s[1]),Nt(s[2]),l),Vt(t,e),e);case"hsla":return 4!==s.length?void zt(e,0,0,0,1):(s[3]=Ot(s[3]),Ft(s,e),Vt(t,e),e);case"hsl":return 3!==s.length?void zt(e,0,0,0,1):(Ft(s,e),Vt(t,e),e);default:return}}zt(e,0,0,0,1)}else{if(4===n.length)return(u=parseInt(n.substr(1),16))>=0&&u<=4095?(zt(e,(3840&u)>>4|(3840&u)>>8,240&u|(240&u)>>4,15&u|(15&u)<<4,1),Vt(t,e),e):void zt(e,0,0,0,1);if(7===n.length){var u=parseInt(n.substr(1),16);return u>=0&&u<=16777215?(zt(e,(16711680&u)>>16,(65280&u)>>8,255&u,1),Vt(t,e),e):void zt(e,0,0,0,1)}}}}function Ft(t,e){var i=(parseFloat(t[0])%360+360)%360/360,n=Ot(t[1]),o=Ot(t[2]),a=o<=.5?o*(n+1):o+n-o*n,r=2*o-a;return e=e||[],zt(e,Lt(255*Et(r,a,i+1/3)),Lt(255*Et(r,a,i)),Lt(255*Et(r,a,i-1/3)),1),4===t.length&&(e[3]=t[3]),e}function Wt(t){if(t){var e,i,n=t[0]/255,o=t[1]/255,a=t[2]/255,r=Math.min(n,o,a),s=Math.max(n,o,a),l=s-r,u=(s+r)/2;if(0===l)e=0,i=0;else{i=u<.5?l/(s+r):l/(2-s-r);var h=((s-n)/6+l/2)/l,c=((s-o)/6+l/2)/l,d=((s-a)/6+l/2)/l;n===s?e=d-c:o===s?e=1/3+h-d:a===s&&(e=2/3+c-h),e<0&&(e+=1),e>1&&(e-=1)}var f=[360*e,i,u];return null!=t[3]&&f.push(t[3]),f}}function Ht(t,e){var i=Gt(t);if(i){for(var n=0;n<3;n++)i[n]=e<0?i[n]*(1-e)|0:(255-i[n])*e+i[n]|0,i[n]>255?i[n]=255:t[n]<0&&(i[n]=0);return qt(i,4===i.length?"rgba":"rgb")}}function Zt(t){var e=Gt(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Ut(t,e,i){if(e&&e.length&&t>=0&&t<=1){i=i||[];var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=e[o],s=e[a],l=n-o;return i[0]=Lt(Rt(r[0],s[0],l)),i[1]=Lt(Rt(r[1],s[1],l)),i[2]=Lt(Rt(r[2],s[2],l)),i[3]=Pt(Rt(r[3],s[3],l)),i}}function Xt(t,e,i){if(e&&e.length&&t>=0&&t<=1){var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=Gt(e[o]),s=Gt(e[a]),l=n-o,u=qt([Lt(Rt(r[0],s[0],l)),Lt(Rt(r[1],s[1],l)),Lt(Rt(r[2],s[2],l)),Pt(Rt(r[3],s[3],l))],"rgba");return i?{color:u,leftIndex:o,rightIndex:a,value:n}:u}}function jt(t,e,i,n){if(t=Gt(t))return t=Wt(t),null!=e&&(t[0]=kt(e)),null!=i&&(t[1]=Ot(i)),null!=n&&(t[2]=Ot(n)),qt(Ft(t),"rgba")}function Yt(t,e){if((t=Gt(t))&&null!=e)return t[3]=Pt(e),qt(t,"rgba")}function qt(t,e){if(t&&t.length){var i=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(i+=","+t[3]),e+"("+i+")"}}function Kt(t,e){return t[e]}function $t(t,e,i){t[e]=i}function Jt(t,e,i){return(e-t)*i+t}function Qt(t,e,i){return i>.5?e:t}function te(t,e,i,n,o){var a=t.length;if(1===o)for(s=0;so)t.length=o;else for(r=n;r=0&&!(m[i]<=e);i--);i=Math.min(i,u-2)}else{for(i=L;ie);i++);i=Math.min(i-1,u-2)}L=i,k=e;var n=m[i+1]-m[i];if(0!==n)if(I=(e-m[i])/n,l)if(A=v[i],T=v[0===i?i:i-1],D=v[i>u-2?u-1:i+1],C=v[i>u-3?u-1:i+2],d)ne(T,A,D,C,I,I*I,I*I*I,r(t,o),g);else{if(f)a=ne(T,A,D,C,I,I*I,I*I*I,P,1),a=re(P);else{if(p)return Qt(A,D,I);a=oe(T,A,D,C,I,I*I,I*I*I)}s(t,o,a)}else if(d)te(v[i],v[i+1],I,r(t,o),g);else{var a;if(f)te(v[i],v[i+1],I,P,1),a=re(P);else{if(p)return Qt(v[i],v[i+1],I);a=Jt(v[i],v[i+1],I)}s(t,o,a)}},ondestroy:i});return e&&"spline"!==e&&(N.easing=e),N}}}function ue(t,e,i,n,o,a,r,s){_(n)?(a=o,o=n,n=0):x(o)?(a=o,o="linear",n=0):x(n)?(a=n,n=0):x(i)?(a=i,i=500):i||(i=500),t.stopAnimation(),he(t,"",t,e,i,n,s);var l=t.animators.slice(),u=l.length;u||a&&a();for(var h=0;h0&&t.animate(e,!1).when(null==o?500:o,s).delay(a||0)}function ce(t,e,i,n){if(e){var o={};o[e]={},o[e][i]=n,t.attr(o)}else t.attr(i,n)}function de(t,e,i,n){i<0&&(t+=i,i=-i),n<0&&(e+=n,n=-n),this.x=t,this.y=e,this.width=i,this.height=n}function fe(t){for(var e=0;t>=eb;)e|=1&t,t>>=1;return t+e}function pe(t,e,i,n){var o=e+1;if(o===i)return 1;if(n(t[o++],t[e])<0){for(;o=0;)o++;return o-e}function ge(t,e,i){for(i--;e>>1])<0?l=a:s=a+1;var u=n-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;u>0;)t[s+u]=t[s+u-1],u--}t[s]=r}}function ve(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])>0){for(s=n-o;l0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}else{for(s=o+1;ls&&(l=s);var u=r;r=o-l,l=o-u}for(r++;r>>1);a(t,e[i+h])>0?r=h+1:l=h}return l}function ye(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])<0){for(s=o+1;ls&&(l=s);var u=r;r=o-l,l=o-u}else{for(s=n-o;l=0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}for(r++;r>>1);a(t,e[i+h])<0?l=h:r=h+1}return l}function xe(t,e){function i(i){var s=a[i],u=r[i],h=a[i+1],c=r[i+1];r[i]=u+c,i===l-3&&(a[i+1]=a[i+2],r[i+1]=r[i+2]),l--;var d=ye(t[h],t,s,u,0,e);s+=d,0!==(u-=d)&&0!==(c=ve(t[s+u-1],t,h,c,c-1,e))&&(u<=c?n(s,u,h,c):o(s,u,h,c))}function n(i,n,o,a){var r=0;for(r=0;r=ib||f>=ib);if(p)break;g<0&&(g=0),g+=2}if((s=g)<1&&(s=1),1===n){for(r=0;r=0;r--)t[f+r]=t[d+r];if(0===n){v=!0;break}}if(t[c--]=u[h--],1==--a){v=!0;break}if(0!=(m=a-ve(t[l],u,0,a,a-1,e))){for(a-=m,f=(c-=m)+1,d=(h-=m)+1,r=0;r=ib||m>=ib);if(v)break;p<0&&(p=0),p+=2}if((s=p)<1&&(s=1),1===a){for(f=(c-=n)+1,d=(l-=n)+1,r=n-1;r>=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else{if(0===a)throw new Error;for(d=c-(a-1),r=0;r=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else for(d=c-(a-1),r=0;r1;){var t=l-2;if(t>=1&&r[t-1]<=r[t]+r[t+1]||t>=2&&r[t-2]<=r[t]+r[t-1])r[t-1]r[t+1])break;i(t)}},this.forceMergeRuns=function(){for(;l>1;){var t=l-2;t>0&&r[t-1]s&&(l=s),me(t,i,i+l,i+a,e),a=l}r.pushRun(i,a),r.mergeRuns(),o-=a,i+=a}while(0!==o);r.forceMergeRuns()}}function we(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}function be(t,e,i){var n=null==e.x?0:e.x,o=null==e.x2?1:e.x2,a=null==e.y?0:e.y,r=null==e.y2?0:e.y2;return e.global||(n=n*i.width+i.x,o=o*i.width+i.x,a=a*i.height+i.y,r=r*i.height+i.y),n=isNaN(n)?0:n,o=isNaN(o)?1:o,a=isNaN(a)?0:a,r=isNaN(r)?0:r,t.createLinearGradient(n,a,o,r)}function Se(t,e,i){var n=i.width,o=i.height,a=Math.min(n,o),r=null==e.x?.5:e.x,s=null==e.y?.5:e.y,l=null==e.r?.5:e.r;return e.global||(r=r*n+i.x,s=s*o+i.y,l*=a),t.createRadialGradient(r,s,0,r,s,l)}function Me(){return!1}function Ie(t,e,i){var n=iw(),o=e.getWidth(),a=e.getHeight(),r=n.style;return r&&(r.position="absolute",r.left=0,r.top=0,r.width=o+"px",r.height=a+"px",n.setAttribute("data-zr-dom-id",t)),n.width=o*i,n.height=a*i,n}function Te(t){if("string"==typeof t){var e=mb.get(t);return e&&e.image}return t}function Ae(t,e,i,n,o){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!i)return e;var a=mb.get(t),r={hostEl:i,cb:n,cbPayload:o};return a?!Ce(e=a.image)&&a.pending.push(r):((e=new Image).onload=e.onerror=De,mb.put(t,e.__cachedImgObj={image:e,pending:[r]}),e.src=e.__zrImageSrc=t),e}return t}return e}function De(){var t=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;exb&&(yb=0,vb={}),yb++,vb[i]=o,o}function ke(t,e,i,n,o,a,r,s){return r?Ne(t,e,i,n,o,a,r,s):Pe(t,e,i,n,o,a,s)}function Pe(t,e,i,n,o,a,r){var s=He(t,e,o,a,r),l=Le(t,e);o&&(l+=o[1]+o[3]);var u=s.outerHeight,h=new de(Oe(0,l,i),Ee(0,u,n),l,u);return h.lineHeight=s.lineHeight,h}function Ne(t,e,i,n,o,a,r,s){var l=Ze(t,{rich:r,truncate:s,font:e,textAlign:i,textPadding:o,textLineHeight:a}),u=l.outerWidth,h=l.outerHeight;return new de(Oe(0,u,i),Ee(0,h,n),u,h)}function Oe(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function Ee(t,e,i){return"middle"===i?t-=e/2:"bottom"===i&&(t-=e),t}function Re(t,e,i){var n=e.x,o=e.y,a=e.height,r=e.width,s=a/2,l="left",u="top";switch(t){case"left":n-=i,o+=s,l="right",u="middle";break;case"right":n+=i+r,o+=s,u="middle";break;case"top":n+=r/2,o-=i,l="center",u="bottom";break;case"bottom":n+=r/2,o+=a+i,l="center";break;case"inside":n+=r/2,o+=s,l="center",u="middle";break;case"insideLeft":n+=i,o+=s,u="middle";break;case"insideRight":n+=r-i,o+=s,l="right",u="middle";break;case"insideTop":n+=r/2,o+=i,l="center";break;case"insideBottom":n+=r/2,o+=a-i,l="center",u="bottom";break;case"insideTopLeft":n+=i,o+=i;break;case"insideTopRight":n+=r-i,o+=i,l="right";break;case"insideBottomLeft":n+=i,o+=a-i,u="bottom";break;case"insideBottomRight":n+=r-i,o+=a-i,l="right",u="bottom"}return{x:n,y:o,textAlign:l,textVerticalAlign:u}}function ze(t,e,i,n,o){if(!e)return"";var a=(t+"").split("\n");o=Be(e,i,n,o);for(var r=0,s=a.length;r=r;l++)s-=r;var u=Le(i,e);return u>s&&(i="",u=0),s=t-u,n.ellipsis=i,n.ellipsisWidth=u,n.contentWidth=s,n.containerWidth=t,n}function Ve(t,e){var i=e.containerWidth,n=e.font,o=e.contentWidth;if(!i)return"";var a=Le(t,n);if(a<=i)return t;for(var r=0;;r++){if(a<=o||r>=e.maxIterations){t+=e.ellipsis;break}var s=0===r?Ge(t,o,e.ascCharWidth,e.cnCharWidth):a>0?Math.floor(t.length*o/a):0;a=Le(t=t.substr(0,s),n)}return""===t&&(t=e.placeholder),t}function Ge(t,e,i,n){for(var o=0,a=0,r=t.length;au)t="",r=[];else if(null!=h)for(var c=Be(h-(i?i[1]+i[3]:0),e,o.ellipsis,{minChar:o.minChar,placeholder:o.placeholder}),d=0,f=r.length;do&&Ue(i,t.substring(o,a)),Ue(i,n[2],n[1]),o=_b.lastIndex}of)return{lines:[],width:0,height:0};k.textWidth=Le(k.text,_);var b=y.textWidth,S=null==b||"auto"===b;if("string"==typeof b&&"%"===b.charAt(b.length-1))k.percentWidth=b,u.push(k),b=0;else{if(S){b=k.textWidth;var M=y.textBackgroundColor,I=M&&M.image;I&&Ce(I=Te(I))&&(b=Math.max(b,I.width*w/I.height))}var T=x?x[1]+x[3]:0;b+=T;var C=null!=d?d-m:null;null!=C&&Cl&&(i*=l/(c=i+n),n*=l/c),o+a>l&&(o*=l/(c=o+a),a*=l/c),n+o>u&&(n*=u/(c=n+o),o*=u/c),i+a>u&&(i*=u/(c=i+a),a*=u/c),t.moveTo(r+i,s),t.lineTo(r+l-n,s),0!==n&&t.arc(r+l-n,s+n,n,-Math.PI/2,0),t.lineTo(r+l,s+u-o),0!==o&&t.arc(r+l-o,s+u-o,o,0,Math.PI/2),t.lineTo(r+a,s+u),0!==a&&t.arc(r+a,s+u-a,a,Math.PI/2,Math.PI),t.lineTo(r,s+i),0!==i&&t.arc(r+i,s+i,i,Math.PI,1.5*Math.PI)}function Ye(t){return qe(t),d(t.rich,qe),t}function qe(t){if(t){t.font=Xe(t);var e=t.textAlign;"middle"===e&&(e="center"),t.textAlign=null==e||Mb[e]?e:"left";var i=t.textVerticalAlign||t.textBaseline;"center"===i&&(i="middle"),t.textVerticalAlign=null==i||Ib[i]?i:"top",t.textPadding&&(t.textPadding=L(t.textPadding))}}function Ke(t,e,i,n,o,a){n.rich?Je(t,e,i,n,o,a):$e(t,e,i,n,o,a)}function $e(t,e,i,n,o,a){var r,s=ii(n),l=!1,u=e.__attrCachedBy===rb.PLAIN_TEXT;a!==sb?(a&&(r=a.style,l=!s&&u&&r),e.__attrCachedBy=s?rb.NONE:rb.PLAIN_TEXT):u&&(e.__attrCachedBy=rb.NONE);var h=n.font||Sb;l&&h===(r.font||Sb)||(e.font=h);var c=t.__computedFont;t.__styleFont!==h&&(t.__styleFont=h,c=t.__computedFont=e.font);var d=n.textPadding,f=n.textLineHeight,p=t.__textCotentBlock;p&&!t.__dirtyText||(p=t.__textCotentBlock=He(i,c,d,f,n.truncate));var g=p.outerHeight,m=p.lines,v=p.lineHeight,y=ai(g,n,o),x=y.baseX,_=y.baseY,w=y.textAlign||"left",b=y.textVerticalAlign;ti(e,n,o,x,_);var S=Ee(_,g,b),M=x,I=S;if(s||d){var T=Le(i,c);d&&(T+=d[1]+d[3]);var A=Oe(x,T,w);s&&ni(t,e,n,A,S,T,g),d&&(M=hi(x,w,d),I+=d[0])}e.textAlign=w,e.textBaseline="middle",e.globalAlpha=n.opacity||1;for(B=0;B=0&&"right"===(_=b[C]).textAlign;)ei(t,e,_,n,M,v,D,"right"),I-=_.width,D-=_.width,C--;for(A+=(a-(A-m)-(y-D)-I)/2;T<=C;)ei(t,e,_=b[T],n,M,v,A+_.width/2,"center"),A+=_.width,T++;v+=M}}function ti(t,e,i,n,o){if(i&&e.textRotation){var a=e.textOrigin;"center"===a?(n=i.width/2+i.x,o=i.height/2+i.y):a&&(n=a[0]+i.x,o=a[1]+i.y),t.translate(n,o),t.rotate(-e.textRotation),t.translate(-n,-o)}}function ei(t,e,i,n,o,a,r,s){var l=n.rich[i.styleName]||{};l.text=i.text;var u=i.textVerticalAlign,h=a+o/2;"top"===u?h=a+i.height/2:"bottom"===u&&(h=a+o-i.height/2),!i.isLineHolder&&ii(l)&&ni(t,e,l,"right"===s?r-i.width:"center"===s?r-i.width/2:r,h-i.height/2,i.width,i.height);var c=i.textPadding;c&&(r=hi(r,s,c),h-=i.height/2-c[2]-i.textHeight/2),ri(e,"shadowBlur",D(l.textShadowBlur,n.textShadowBlur,0)),ri(e,"shadowColor",l.textShadowColor||n.textShadowColor||"transparent"),ri(e,"shadowOffsetX",D(l.textShadowOffsetX,n.textShadowOffsetX,0)),ri(e,"shadowOffsetY",D(l.textShadowOffsetY,n.textShadowOffsetY,0)),ri(e,"textAlign",s),ri(e,"textBaseline","middle"),ri(e,"font",i.font||Sb);var d=si(l.textStroke||n.textStroke,p),f=li(l.textFill||n.textFill),p=A(l.textStrokeWidth,n.textStrokeWidth);d&&(ri(e,"lineWidth",p),ri(e,"strokeStyle",d),e.strokeText(i.text,r,h)),f&&(ri(e,"fillStyle",f),e.fillText(i.text,r,h))}function ii(t){return!!(t.textBackgroundColor||t.textBorderWidth&&t.textBorderColor)}function ni(t,e,i,n,o,a,r){var s=i.textBackgroundColor,l=i.textBorderWidth,u=i.textBorderColor,h=_(s);if(ri(e,"shadowBlur",i.textBoxShadowBlur||0),ri(e,"shadowColor",i.textBoxShadowColor||"transparent"),ri(e,"shadowOffsetX",i.textBoxShadowOffsetX||0),ri(e,"shadowOffsetY",i.textBoxShadowOffsetY||0),h||l&&u){e.beginPath();var c=i.textBorderRadius;c?je(e,{x:n,y:o,width:a,height:r,r:c}):e.rect(n,o,a,r),e.closePath()}if(h)if(ri(e,"fillStyle",s),null!=i.fillOpacity){f=e.globalAlpha;e.globalAlpha=i.fillOpacity*i.opacity,e.fill(),e.globalAlpha=f}else e.fill();else if(w(s)){var d=s.image;(d=Ae(d,null,t,oi,s))&&Ce(d)&&e.drawImage(d,n,o,a,r)}if(l&&u)if(ri(e,"lineWidth",l),ri(e,"strokeStyle",u),null!=i.strokeOpacity){var f=e.globalAlpha;e.globalAlpha=i.strokeOpacity*i.opacity,e.stroke(),e.globalAlpha=f}else e.stroke()}function oi(t,e){e.image=t}function ai(t,e,i){var n=e.x||0,o=e.y||0,a=e.textAlign,r=e.textVerticalAlign;if(i){var s=e.textPosition;if(s instanceof Array)n=i.x+ui(s[0],i.width),o=i.y+ui(s[1],i.height);else{var l=Re(s,i,e.textDistance);n=l.x,o=l.y,a=a||l.textAlign,r=r||l.textVerticalAlign}var u=e.textOffset;u&&(n+=u[0],o+=u[1])}return{baseX:n,baseY:o,textAlign:a,textVerticalAlign:r}}function ri(t,e,i){return t[e]=ab(t,e,i),t[e]}function si(t,e){return null==t||e<=0||"transparent"===t||"none"===t?null:t.image||t.colorStops?"#000":t}function li(t){return null==t||"none"===t?null:t.image||t.colorStops?"#000":t}function ui(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t}function hi(t,e,i){return"right"===e?t-i[1]:"center"===e?t+i[3]/2-i[1]/2:t+i[3]}function ci(t,e){return null!=t&&(t||e.textBackgroundColor||e.textBorderWidth&&e.textBorderColor||e.textPadding)}function di(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&"style"!==e&&(this[e]=t[e]);this.style=new ub(t.style,this),this._rect=null,this.__clipPaths=[]}function fi(t){di.call(this,t)}function pi(t){return parseInt(t,10)}function gi(t){return!!t&&(!!t.__builtin__||"function"==typeof t.resize&&"function"==typeof t.refresh)}function mi(t,e,i){return Cb.copy(t.getBoundingRect()),t.transform&&Cb.applyTransform(t.transform),Lb.width=e,Lb.height=i,!Cb.intersect(Lb)}function vi(t,e){if(t===e)return!1;if(!t||!e||t.length!==e.length)return!0;for(var i=0;i=i.length&&i.push({option:t})}}),i}function Ni(t){var e=R();Zb(t,function(t,i){var n=t.exist;n&&e.set(n.id,t)}),Zb(t,function(t,i){var n=t.option;k(!n||null==n.id||!e.get(n.id)||e.get(n.id)===t,"id duplicates: "+(n&&n.id)),n&&null!=n.id&&e.set(n.id,t),!t.keyInfo&&(t.keyInfo={})}),Zb(t,function(t,i){var n=t.exist,o=t.option,a=t.keyInfo;if(Ub(o)){if(a.name=null!=o.name?o.name+"":n?n.name:jb+i,n)a.id=n.id;else if(null!=o.id)a.id=o.id+"";else{var r=0;do{a.id="\0"+a.name+"\0"+r++}while(e.get(a.id))}e.set(a.id,t)}})}function Oi(t){var e=t.name;return!(!e||!e.indexOf(jb))}function Ei(t){return Ub(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Ri(t,e){function i(t,e,i){for(var n=0,o=t.length;n-rS&&trS||t<-rS}function tn(t,e,i,n,o){var a=1-o;return a*a*(a*t+3*o*e)+o*o*(o*n+3*a*i)}function en(t,e,i,n,o){var a=1-o;return 3*(((e-t)*a+2*(i-e)*o)*a+(n-i)*o*o)}function nn(t,e,i,n,o,a){var r=n+3*(e-i)-t,s=3*(i-2*e+t),l=3*(e-t),u=t-o,h=s*s-3*r*l,c=s*l-9*r*u,d=l*l-3*s*u,f=0;if(Ji(h)&&Ji(c))Ji(s)?a[0]=0:(M=-l/s)>=0&&M<=1&&(a[f++]=M);else{var p=c*c-4*h*d;if(Ji(p)){var g=c/h,m=-g/2;(M=-s/r+g)>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m)}else if(p>0){var v=aS(p),y=h*s+1.5*r*(-c+v),x=h*s+1.5*r*(-c-v);(M=(-s-((y=y<0?-oS(-y,uS):oS(y,uS))+(x=x<0?-oS(-x,uS):oS(x,uS))))/(3*r))>=0&&M<=1&&(a[f++]=M)}else{var _=(2*h*s-3*r*c)/(2*aS(h*h*h)),w=Math.acos(_)/3,b=aS(h),S=Math.cos(w),M=(-s-2*b*S)/(3*r),m=(-s+b*(S+lS*Math.sin(w)))/(3*r),I=(-s+b*(S-lS*Math.sin(w)))/(3*r);M>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m),I>=0&&I<=1&&(a[f++]=I)}}return f}function on(t,e,i,n,o){var a=6*i-12*e+6*t,r=9*e+3*n-3*t-9*i,s=3*e-3*t,l=0;if(Ji(r))Qi(a)&&(c=-s/a)>=0&&c<=1&&(o[l++]=c);else{var u=a*a-4*r*s;if(Ji(u))o[0]=-a/(2*r);else if(u>0){var h=aS(u),c=(-a+h)/(2*r),d=(-a-h)/(2*r);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function an(t,e,i,n,o,a){var r=(e-t)*o+t,s=(i-e)*o+e,l=(n-i)*o+i,u=(s-r)*o+r,h=(l-s)*o+s,c=(h-u)*o+u;a[0]=t,a[1]=r,a[2]=u,a[3]=c,a[4]=c,a[5]=h,a[6]=l,a[7]=n}function rn(t,e,i,n,o,a,r,s,l,u,h){var c,d,f,p,g,m=.005,v=1/0;hS[0]=l,hS[1]=u;for(var y=0;y<1;y+=.05)cS[0]=tn(t,i,o,r,y),cS[1]=tn(e,n,a,s,y),(p=hw(hS,cS))=0&&p=0&&c<=1&&(o[l++]=c);else{var u=r*r-4*a*s;if(Ji(u))(c=-r/(2*a))>=0&&c<=1&&(o[l++]=c);else if(u>0){var h=aS(u),c=(-r+h)/(2*a),d=(-r-h)/(2*a);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function hn(t,e,i){var n=t+i-2*e;return 0===n?.5:(t-e)/n}function cn(t,e,i,n,o){var a=(e-t)*n+t,r=(i-e)*n+e,s=(r-a)*n+a;o[0]=t,o[1]=a,o[2]=s,o[3]=s,o[4]=r,o[5]=i}function dn(t,e,i,n,o,a,r,s,l){var u,h=.005,c=1/0;hS[0]=r,hS[1]=s;for(var d=0;d<1;d+=.05)cS[0]=sn(t,i,o,d),cS[1]=sn(e,n,a,d),(m=hw(hS,cS))=0&&m1e-4)return s[0]=t-i,s[1]=e-n,l[0]=t+i,void(l[1]=e+n);if(yS[0]=mS(o)*i+t,yS[1]=gS(o)*n+e,xS[0]=mS(a)*i+t,xS[1]=gS(a)*n+e,u(s,yS,xS),h(l,yS,xS),(o%=vS)<0&&(o+=vS),(a%=vS)<0&&(a+=vS),o>a&&!r?a+=vS:oo&&(_S[0]=mS(f)*i+t,_S[1]=gS(f)*n+e,u(s,_S,s),h(l,_S,l))}function yn(t,e,i,n,o,a,r){if(0===o)return!1;var s=o,l=0,u=t;if(r>e+s&&r>n+s||rt+s&&a>i+s||ae+c&&h>n+c&&h>a+c&&h>s+c||ht+c&&u>i+c&&u>o+c&&u>r+c||ue+u&&l>n+u&&l>a+u||lt+u&&s>i+u&&s>o+u||si||h+uo&&(o+=zS);var d=Math.atan2(l,s);return d<0&&(d+=zS),d>=n&&d<=o||d+zS>=n&&d+zS<=o}function Sn(t,e,i,n,o,a){if(a>e&&a>n||ao?r:0}function Mn(t,e){return Math.abs(t-e)e&&u>n&&u>a&&u>s||u1&&In(),c=tn(e,n,a,s,WS[0]),p>1&&(d=tn(e,n,a,s,WS[1]))),2===p?me&&s>n&&s>a||s=0&&u<=1){for(var h=0,c=sn(e,n,a,u),d=0;di||s<-i)return 0;u=Math.sqrt(i*i-s*s);FS[0]=-u,FS[1]=u;var l=Math.abs(n-o);if(l<1e-4)return 0;if(l%VS<1e-4){n=0,o=VS;p=a?1:-1;return r>=FS[0]+t&&r<=FS[1]+t?p:0}if(a){var u=n;n=wn(o),o=wn(u)}else n=wn(n),o=wn(o);n>o&&(o+=VS);for(var h=0,c=0;c<2;c++){var d=FS[c];if(d+t>r){var f=Math.atan2(s,d),p=a?1:-1;f<0&&(f=VS+f),(f>=n&&f<=o||f+VS>=n&&f+VS<=o)&&(f>Math.PI/2&&f<1.5*Math.PI&&(p=-p),h+=p)}}return h}function Cn(t,e,i,n,o){for(var a=0,r=0,s=0,l=0,u=0,h=0;h1&&(i||(a+=Sn(r,s,l,u,n,o))),1===h&&(l=r=t[h],u=s=t[h+1]),c){case BS.M:r=l=t[h++],s=u=t[h++];break;case BS.L:if(i){if(yn(r,s,t[h],t[h+1],e,n,o))return!0}else a+=Sn(r,s,t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.C:if(i){if(xn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=Tn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.Q:if(i){if(_n(r,s,t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=An(r,s,t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.A:var d=t[h++],f=t[h++],p=t[h++],g=t[h++],m=t[h++],v=t[h++];h+=1;var y=1-t[h++],x=Math.cos(m)*p+d,_=Math.sin(m)*g+f;h>1?a+=Sn(r,s,x,_,n,o):(l=x,u=_);var w=(n-d)*g/p+d;if(i){if(bn(d,f,g,m,m+v,y,e,w,o))return!0}else a+=Dn(d,f,g,m,m+v,y,w,o);r=Math.cos(m+v)*p+d,s=Math.sin(m+v)*g+f;break;case BS.R:l=r=t[h++],u=s=t[h++];var x=l+t[h++],_=u+t[h++];if(i){if(yn(l,u,x,u,e,n,o)||yn(x,u,x,_,e,n,o)||yn(x,_,l,_,e,n,o)||yn(l,_,l,u,e,n,o))return!0}else a+=Sn(x,u,x,_,n,o),a+=Sn(l,_,l,u,n,o);break;case BS.Z:if(i){if(yn(r,s,l,u,e,n,o))return!0}else a+=Sn(r,s,l,u,n,o);r=l,s=u}}return i||Mn(s,u)||(a+=Sn(r,s,l,u,n,o)||0),0!==a}function Ln(t,e,i){return Cn(t,0,!1,e,i)}function kn(t,e,i,n){return Cn(t,e,!0,i,n)}function Pn(t){di.call(this,t),this.path=null}function Nn(t,e,i,n,o,a,r,s,l,u,h){var c=l*(tM/180),d=QS(c)*(t-i)/2+JS(c)*(e-n)/2,f=-1*JS(c)*(t-i)/2+QS(c)*(e-n)/2,p=d*d/(r*r)+f*f/(s*s);p>1&&(r*=$S(p),s*=$S(p));var g=(o===a?-1:1)*$S((r*r*(s*s)-r*r*(f*f)-s*s*(d*d))/(r*r*(f*f)+s*s*(d*d)))||0,m=g*r*f/s,v=g*-s*d/r,y=(t+i)/2+QS(c)*m-JS(c)*v,x=(e+n)/2+JS(c)*m+QS(c)*v,_=nM([1,0],[(d-m)/r,(f-v)/s]),w=[(d-m)/r,(f-v)/s],b=[(-1*d-m)/r,(-1*f-v)/s],S=nM(w,b);iM(w,b)<=-1&&(S=tM),iM(w,b)>=1&&(S=0),0===a&&S>0&&(S-=2*tM),1===a&&S<0&&(S+=2*tM),h.addData(u,y,x,r,s,_,S,c,a)}function On(t){if(!t)return new ES;for(var e,i=0,n=0,o=i,a=n,r=new ES,s=ES.CMD,l=t.match(oM),u=0;u=2){if(o&&"spline"!==o){var a=fM(n,o,i,e.smoothConstraint);t.moveTo(n[0][0],n[0][1]);for(var r=n.length,s=0;s<(i?r:r-1);s++){var l=a[2*s],u=a[2*s+1],h=n[(s+1)%r];t.bezierCurveTo(l[0],l[1],u[0],u[1],h[0],h[1])}}else{"spline"===o&&(n=dM(n,i)),t.moveTo(n[0][0],n[0][1]);for(var s=1,c=n.length;s=0)?(i={textFill:null,textStroke:t.textStroke,textStrokeWidth:t.textStrokeWidth},t.textFill="#fff",null==t.textStroke&&(t.textStroke=a,null==t.textStrokeWidth&&(t.textStrokeWidth=2))):null!=a&&(i={textFill:null},t.textFill=a),i&&(t.insideRollback=i)}}function bo(t){var e=t.insideRollback;e&&(t.textFill=e.textFill,t.textStroke=e.textStroke,t.textStrokeWidth=e.textStrokeWidth,t.insideRollback=null)}function So(t,e){var i=e||e.getModel("textStyle");return P([t.fontStyle||i&&i.getShallow("fontStyle")||"",t.fontWeight||i&&i.getShallow("fontWeight")||"",(t.fontSize||i&&i.getShallow("fontSize")||12)+"px",t.fontFamily||i&&i.getShallow("fontFamily")||"sans-serif"].join(" "))}function Mo(t,e,i,n,o,a){if("function"==typeof o&&(a=o,o=null),n&&n.isAnimationEnabled()){var r=t?"Update":"",s=n.getShallow("animationDuration"+r),l=n.getShallow("animationEasing"+r),u=n.getShallow("animationDelay"+r);"function"==typeof u&&(u=u(o,n.getAnimationDelayParams?n.getAnimationDelayParams(e,o):null)),"function"==typeof s&&(s=s(o)),s>0?e.animateTo(i,s,u||0,l,a,!!a):(e.stopAnimation(),e.attr(i),a&&a())}else e.stopAnimation(),e.attr(i),a&&a()}function Io(t,e,i,n,o){Mo(!0,t,e,i,n,o)}function To(t,e,i,n,o){Mo(!1,t,e,i,n,o)}function Ao(t,e){for(var i=_t([]);t&&t!==e;)bt(i,t.getLocalTransform(),i),t=t.parent;return i}function Do(t,e,i){return e&&!c(e)&&(e=Tw.getLocalTransform(e)),i&&(e=Tt([],e)),Q([],t,e)}function Co(t,e,i){var n=0===e[4]||0===e[5]||0===e[0]?1:Math.abs(2*e[4]/e[0]),o=0===e[4]||0===e[5]||0===e[2]?1:Math.abs(2*e[4]/e[2]),a=["left"===t?-n:"right"===t?n:0,"top"===t?-o:"bottom"===t?o:0];return a=Do(a,e,i),Math.abs(a[0])>Math.abs(a[1])?a[0]>0?"right":"left":a[1]>0?"bottom":"top"}function Lo(t,e,i,n){function o(t){var e={position:F(t.position),rotation:t.rotation};return t.shape&&(e.shape=a({},t.shape)),e}if(t&&e){var r=function(t){var e={};return t.traverse(function(t){!t.isGroup&&t.anid&&(e[t.anid]=t)}),e}(t);e.traverse(function(t){if(!t.isGroup&&t.anid){var e=r[t.anid];if(e){var n=o(t);t.attr(o(e)),Io(t,n,i,t.dataIndex)}}})}}function ko(t,e){return f(t,function(t){var i=t[0];i=LM(i,e.x),i=kM(i,e.x+e.width);var n=t[1];return n=LM(n,e.y),n=kM(n,e.y+e.height),[i,n]})}function Po(t,e,i){var n=(e=a({rectHover:!0},e)).style={strokeNoScale:!0};if(i=i||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(n.image=t.slice(8),r(n,i),new fi(e)):Xn(t.replace("path://",""),e,i,"center")}function No(t,e,i){this.parentModel=e,this.ecModel=i,this.option=t}function Oo(t,e,i){for(var n=0;n0){if(t<=e[0])return i[0];if(t>=e[1])return i[1]}else{if(t>=e[0])return i[0];if(t<=e[1])return i[1]}else{if(t===e[0])return i[0];if(t===e[1])return i[1]}return(t-e[0])/o*a+i[0]}function Vo(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?zo(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function Go(t,e,i){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),i?t:+t}function Fo(t){return t.sort(function(t,e){return t-e}),t}function Wo(t){if(t=+t,isNaN(t))return 0;for(var e=1,i=0;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Ho(t){var e=t.toString(),i=e.indexOf("e");if(i>0){var n=+e.slice(i+1);return n<0?-n:0}var o=e.indexOf(".");return o<0?0:e.length-1-o}function Zo(t,e){var i=Math.log,n=Math.LN10,o=Math.floor(i(t[1]-t[0])/n),a=Math.round(i(Math.abs(e[1]-e[0]))/n),r=Math.min(Math.max(-o+a,0),20);return isFinite(r)?r:20}function Uo(t,e,i){if(!t[e])return 0;var n=p(t,function(t,e){return t+(isNaN(e)?0:e)},0);if(0===n)return 0;for(var o=Math.pow(10,i),a=f(t,function(t){return(isNaN(t)?0:t)/n*o*100}),r=100*o,s=f(a,function(t){return Math.floor(t)}),l=p(s,function(t,e){return t+e},0),u=f(a,function(t,e){return t-s[e]});lh&&(h=u[d],c=d);++s[c],u[c]=0,++l}return s[e]/o}function Xo(t){var e=2*Math.PI;return(t%e+e)%e}function jo(t){return t>-UM&&t=-20?+t.toFixed(n<0?-n:0):t}function Jo(t){function e(t,i,n){return t.interval[n]=0}function ta(t){return isNaN(t)?"-":(t=(t+"").split("."))[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(t.length>1?"."+t[1]:"")}function ea(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()}),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}function ia(t){return null==t?"":(t+"").replace(KM,function(t,e){return $M[e]})}function na(t,e,i){y(e)||(e=[e]);var n=e.length;if(!n)return"";for(var o=e[0].$vars||[],a=0;a':'':{renderMode:o,content:"{marker"+a+"|} ",style:{color:i}}:""}function ra(t,e){return t+="","0000".substr(0,e-t.length)+t}function sa(t,e,i){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var n=Yo(e),o=i?"UTC":"",a=n["get"+o+"FullYear"](),r=n["get"+o+"Month"]()+1,s=n["get"+o+"Date"](),l=n["get"+o+"Hours"](),u=n["get"+o+"Minutes"](),h=n["get"+o+"Seconds"](),c=n["get"+o+"Milliseconds"]();return t=t.replace("MM",ra(r,2)).replace("M",r).replace("yyyy",a).replace("yy",a%100).replace("dd",ra(s,2)).replace("d",s).replace("hh",ra(l,2)).replace("h",l).replace("mm",ra(u,2)).replace("m",u).replace("ss",ra(h,2)).replace("s",h).replace("SSS",ra(c,3))}function la(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}function ua(t,e,i,n,o){var a=0,r=0;null==n&&(n=1/0),null==o&&(o=1/0);var s=0;e.eachChild(function(l,u){var h,c,d=l.position,f=l.getBoundingRect(),p=e.childAt(u+1),g=p&&p.getBoundingRect();if("horizontal"===t){var m=f.width+(g?-g.x+f.x:0);(h=a+m)>n||l.newline?(a=0,h=m,r+=s+i,s=f.height):s=Math.max(s,f.height)}else{var v=f.height+(g?-g.y+f.y:0);(c=r+v)>o||l.newline?(a+=s+i,r=0,c=v,s=f.width):s=Math.max(s,f.width)}l.newline||(d[0]=a,d[1]=r,"horizontal"===t?a=h+i:r=c+i)})}function ha(t,e,i){var n=e.width,o=e.height,a=Vo(t.x,n),r=Vo(t.y,o),s=Vo(t.x2,n),l=Vo(t.y2,o);return(isNaN(a)||isNaN(parseFloat(t.x)))&&(a=0),(isNaN(s)||isNaN(parseFloat(t.x2)))&&(s=n),(isNaN(r)||isNaN(parseFloat(t.y)))&&(r=0),(isNaN(l)||isNaN(parseFloat(t.y2)))&&(l=o),i=qM(i||0),{width:Math.max(s-a-i[1]-i[3],0),height:Math.max(l-r-i[0]-i[2],0)}}function ca(t,e,i){i=qM(i||0);var n=e.width,o=e.height,a=Vo(t.left,n),r=Vo(t.top,o),s=Vo(t.right,n),l=Vo(t.bottom,o),u=Vo(t.width,n),h=Vo(t.height,o),c=i[2]+i[0],d=i[1]+i[3],f=t.aspect;switch(isNaN(u)&&(u=n-s-d-a),isNaN(h)&&(h=o-l-c-r),null!=f&&(isNaN(u)&&isNaN(h)&&(f>n/o?u=.8*n:h=.8*o),isNaN(u)&&(u=f*h),isNaN(h)&&(h=u/f)),isNaN(a)&&(a=n-s-u-d),isNaN(r)&&(r=o-l-h-c),t.left||t.right){case"center":a=n/2-u/2-i[3];break;case"right":a=n-u-d}switch(t.top||t.bottom){case"middle":case"center":r=o/2-h/2-i[0];break;case"bottom":r=o-h-c}a=a||0,r=r||0,isNaN(u)&&(u=n-d-a-(s||0)),isNaN(h)&&(h=o-c-r-(l||0));var p=new de(a+i[3],r+i[0],u,h);return p.margin=i,p}function da(t,e,i,n,o){var a=!o||!o.hv||o.hv[0],s=!o||!o.hv||o.hv[1],l=o&&o.boundingMode||"all";if(a||s){var u;if("raw"===l)u="group"===t.type?new de(0,0,+e.width||0,+e.height||0):t.getBoundingRect();else if(u=t.getBoundingRect(),t.needLocalTransform()){var h=t.getLocalTransform();(u=u.clone()).applyTransform(h)}e=ca(r({width:u.width,height:u.height},e),i,n);var c=t.position,d=a?e.x-u.x:0,f=s?e.y-u.y:0;t.attr("position","raw"===l?[d,f]:[c[0]+d,c[1]+f])}}function fa(t,e){return null!=t[oI[e][0]]||null!=t[oI[e][1]]&&null!=t[oI[e][2]]}function pa(t,e,i){function n(i,n){var r={},l=0,u={},h=0;if(iI(i,function(e){u[e]=t[e]}),iI(i,function(t){o(e,t)&&(r[t]=u[t]=e[t]),a(r,t)&&l++,a(u,t)&&h++}),s[n])return a(e,i[1])?u[i[2]]=null:a(e,i[2])&&(u[i[1]]=null),u;if(2!==h&&l){if(l>=2)return r;for(var c=0;ce)return t[n];return t[i-1]}function ya(t){var e=t.get("coordinateSystem"),i={coordSysName:e,coordSysDims:[],axisMap:R(),categoryAxisMap:R()},n=fI[e];if(n)return n(t,i,i.axisMap,i.categoryAxisMap),i}function xa(t){return"category"===t.get("type")}function _a(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===vI?{}:[]),this.sourceFormat=t.sourceFormat||yI,this.seriesLayoutBy=t.seriesLayoutBy||_I,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&R(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}function wa(t){var e=t.option.source,i=yI;if(S(e))i=xI;else if(y(e)){0===e.length&&(i=gI);for(var n=0,o=e.length;n=e:"max"===i?t<=e:t===e}function Xa(t,e){return t.join(",")===e.join(",")}function ja(t,e){AI(e=e||{},function(e,i){if(null!=e){var n=t[i];if(lI.hasClass(i)){e=Di(e);var o=Pi(n=Di(n),e);t[i]=CI(o,function(t){return t.option&&t.exist?LI(t.exist,t.option,!0):t.exist||t.option})}else t[i]=LI(n,e,!0)}})}function Ya(t){var e=t&&t.itemStyle;if(e)for(var i=0,o=OI.length;i=0;p--){var g=t[p];if(s||(d=g.data.rawIndexOf(g.stackedByDimension,c)),d>=0){var m=g.data.getByRawIndex(g.stackResultDimension,d);if(h>=0&&m>0||h<=0&&m<0){h+=m,f=m;break}}}return n[0]=h,n[1]=f,n});r.hostModel.setData(l),e.data=l})}function rr(t,e){_a.isInstance(t)||(t=_a.seriesDataToSource(t)),this._source=t;var i=this._data=t.data,n=t.sourceFormat;n===xI&&(this._offset=0,this._dimSize=e,this._data=i),a(this,GI[n===gI?n+"_"+t.seriesLayoutBy:n])}function sr(){return this._data.length}function lr(t){return this._data[t]}function ur(t){for(var e=0;ee.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Mr(t,e){d(t.CHANGABLE_METHODS,function(i){t.wrapMethod(i,v(Ir,e))})}function Ir(t){var e=Tr(t);e&&e.setOutputEnd(this.count())}function Tr(t){var e=(t.ecModel||{}).scheduler,i=e&&e.getPipeline(t.uid);if(i){var n=i.currentTask;if(n){var o=n.agentStubMap;o&&(n=o.get(t.uid))}return n}}function Ar(){this.group=new tb,this.uid=Ro("viewChart"),this.renderTask=gr({plan:Lr,reset:kr}),this.renderTask.context={view:this}}function Dr(t,e){if(t&&(t.trigger(e),"group"===t.type))for(var i=0;i=0?n():c=setTimeout(n,-a),u=o};return d.clear=function(){c&&(clearTimeout(c),c=null)},d.debounceNextCall=function(t){l=t},d}function Nr(t,e,i,n){var o=t[e];if(o){var a=o[iT]||o,r=o[oT];if(o[nT]!==i||r!==n){if(null==i||!n)return t[e]=a;(o=t[e]=Pr(a,i,"debounce"===n))[iT]=a,o[oT]=n,o[nT]=i}return o}}function Or(t,e){var i=t[e];i&&i[iT]&&(t[e]=i[iT])}function Er(t,e,i,n){this.ecInstance=t,this.api=e,this.unfinished;var i=this._dataProcessorHandlers=i.slice(),n=this._visualHandlers=n.slice();this._allHandlers=i.concat(n),this._stageTaskMap=R()}function Rr(t,e,i,n,o){function a(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}o=o||{};var r;d(e,function(e,s){if(!o.visualType||o.visualType===e.visualType){var l=t._stageTaskMap.get(e.uid),u=l.seriesTaskMap,h=l.overallTask;if(h){var c,d=h.agentStubMap;d.each(function(t){a(o,t)&&(t.dirty(),c=!0)}),c&&h.dirty(),hT(h,n);var f=t.getPerformArgs(h,o.block);d.each(function(t){t.perform(f)}),r|=h.perform(f)}else u&&u.each(function(s,l){a(o,s)&&s.dirty();var u=t.getPerformArgs(s,o.block);u.skip=!e.performRawSeries&&i.isSeriesFiltered(s.context.model),hT(s,n),r|=s.perform(u)})}}),t.unfinished|=r}function zr(t,e,i,n,o){function a(i){var a=i.uid,s=r.get(a)||r.set(a,gr({plan:Hr,reset:Zr,count:Xr}));s.context={model:i,ecModel:n,api:o,useClearVisual:e.isVisual&&!e.isLayout,plan:e.plan,reset:e.reset,scheduler:t},jr(t,i,s)}var r=i.seriesTaskMap||(i.seriesTaskMap=R()),s=e.seriesType,l=e.getTargetSeries;e.createOnAllSeries?n.eachRawSeries(a):s?n.eachRawSeriesByType(s,a):l&&l(n,o).each(a);var u=t._pipelineMap;r.each(function(t,e){u.get(e)||(t.dispose(),r.removeKey(e))})}function Br(t,e,i,n,o){function a(e){var i=e.uid,n=s.get(i);n||(n=s.set(i,gr({reset:Gr,onDirty:Wr})),r.dirty()),n.context={model:e,overallProgress:h,modifyOutputEnd:c},n.agent=r,n.__block=h,jr(t,e,n)}var r=i.overallTask=i.overallTask||gr({reset:Vr});r.context={ecModel:n,api:o,overallReset:e.overallReset,scheduler:t};var s=r.agentStubMap=r.agentStubMap||R(),l=e.seriesType,u=e.getTargetSeries,h=!0,c=e.modifyOutputEnd;l?n.eachRawSeriesByType(l,a):u?u(n,o).each(a):(h=!1,d(n.getSeries(),a));var f=t._pipelineMap;s.each(function(t,e){f.get(e)||(t.dispose(),r.dirty(),s.removeKey(e))})}function Vr(t){t.overallReset(t.ecModel,t.api,t.payload)}function Gr(t,e){return t.overallProgress&&Fr}function Fr(){this.agent.dirty(),this.getDownstream().dirty()}function Wr(){this.agent&&this.agent.dirty()}function Hr(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function Zr(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=Di(t.reset(t.model,t.ecModel,t.api,t.payload));return e.length>1?f(e,function(t,e){return Ur(e)}):cT}function Ur(t){return function(e,i){var n=i.data,o=i.resetDefines[t];if(o&&o.dataEach)for(var a=e.start;a0?parseInt(n,10)/100:n?parseFloat(n):0;var o=i.getAttribute("stop-color")||"#000000";e.addColorStop(n,o)}i=i.nextSibling}}function Qr(t,e){t&&t.__inheritedStyle&&(e.__inheritedStyle||(e.__inheritedStyle={}),r(e.__inheritedStyle,t.__inheritedStyle))}function ts(t){for(var e=P(t).split(_T),i=[],n=0;n0;a-=2){var r=o[a],s=o[a-1];switch(n=n||xt(),s){case"translate":r=P(r).split(_T),St(n,n,[parseFloat(r[0]),parseFloat(r[1]||0)]);break;case"scale":r=P(r).split(_T),It(n,n,[parseFloat(r[0]),parseFloat(r[1]||r[0])]);break;case"rotate":r=P(r).split(_T),Mt(n,n,parseFloat(r[0]));break;case"skew":r=P(r).split(_T),console.warn("Skew transform is not supported yet");break;case"matrix":r=P(r).split(_T);n[0]=parseFloat(r[0]),n[1]=parseFloat(r[1]),n[2]=parseFloat(r[2]),n[3]=parseFloat(r[3]),n[4]=parseFloat(r[4]),n[5]=parseFloat(r[5])}}e.setLocalTransform(n)}}function os(t){var e=t.getAttribute("style"),i={};if(!e)return i;var n={};TT.lastIndex=0;for(var o;null!=(o=TT.exec(e));)n[o[1]]=o[2];for(var a in ST)ST.hasOwnProperty(a)&&null!=n[a]&&(i[ST[a]]=n[a]);return i}function as(t,e,i){var n=e/t.width,o=i/t.height,a=Math.min(n,o);return{scale:[a,a],position:[-(t.x+t.width/2)*a+e/2,-(t.y+t.height/2)*a+i/2]}}function rs(t,e){return(new $r).parse(t,e)}function ss(t){return function(e,i,n){e=e&&e.toLowerCase(),fw.prototype[t].call(this,e,i,n)}}function ls(){fw.call(this)}function us(t,e,n){function o(t,e){return t.__prio-e.__prio}n=n||{},"string"==typeof e&&(e=JT[e]),this.id,this.group,this._dom=t;var a=this._zr=Ii(t,{renderer:n.renderer||"canvas",devicePixelRatio:n.devicePixelRatio,width:n.width,height:n.height});this._throttledZrFlush=Pr(m(a.flush,a),17),(e=i(e))&&BI(e,!0),this._theme=e,this._chartsViews=[],this._chartsMap={},this._componentsViews=[],this._componentsMap={},this._coordSysMgr=new Fa;var r=this._api=As(this);_e($T,o),_e(YT,o),this._scheduler=new Er(this,r,YT,$T),fw.call(this,this._ecEventProcessor=new Ds),this._messageCenter=new ls,this._initEvents(),this.resize=m(this.resize,this),this._pendingActions=[],a.animation.on("frame",this._onframe,this),vs(a,this),N(this)}function hs(t,e,i){var n,o=this._model,a=this._coordSysMgr.getCoordinateSystems();e=Vi(o,e);for(var r=0;re.get("hoverLayerThreshold")&&!U_.node&&i.traverse(function(t){t.isGroup||(t.useHoverLayer=!0)})}function Is(t,e){var i=t.get("blendMode")||null;e.group.traverse(function(t){t.isGroup||t.style.blend!==i&&t.setStyle("blend",i),t.eachPendingDisplayable&&t.eachPendingDisplayable(function(t){t.setStyle("blend",i)})})}function Ts(t,e){var i=t.get("z"),n=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=n&&(t.zlevel=n))})}function As(t){var e=t._coordSysMgr;return a(new Ga(t),{getCoordinateSystems:m(e.getCoordinateSystems,e),getComponentByElement:function(e){for(;e;){var i=e.__ecComponentInfo;if(null!=i)return t._model.getComponent(i.mainType,i.index);e=e.parent}}})}function Ds(){this.eventInfo}function Cs(t){function e(t,e){for(var n=0;n65535?dA:pA}function Js(t){var e=t.constructor;return e===Array?t.slice():new e(t)}function Qs(t,e){d(gA.concat(e.__wrappedMethods||[]),function(i){e.hasOwnProperty(i)&&(t[i]=e[i])}),t.__wrappedMethods=e.__wrappedMethods,d(mA,function(n){t[n]=i(e[n])}),t._calculationInfo=a(e._calculationInfo)}function tl(t,e,i,n,o){var a=cA[e.type],r=n-1,s=e.name,l=t[s][r];if(l&&l.length=0?this._indices[t]:-1}function al(t,e){var i=t._idList[e];return null==i&&(i=il(t,t._idDimIdx,e)),null==i&&(i=hA+e),i}function rl(t){return y(t)||(t=[t]),t}function sl(t,e){var i=t.dimensions,n=new vA(f(i,t.getDimensionInfo,t),t.hostModel);Qs(n,t);for(var o=n._storage={},a=t._storage,r=0;r=0?(o[s]=ll(a[s]),n._rawExtent[s]=ul(),n._extent[s]=null):o[s]=a[s])}return n}function ll(t){for(var e=new Array(t.length),i=0;in&&(r=o.interval=n);var s=o.intervalPrecision=Ml(r);return Tl(o.niceTickExtent=[MA(Math.ceil(t[0]/r)*r,s),MA(Math.floor(t[1]/r)*r,s)],t),o}function Ml(t){return Ho(t)+2}function Il(t,e,i){t[e]=Math.max(Math.min(t[e],i[1]),i[0])}function Tl(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),Il(t,0,e),Il(t,1,e),t[0]>t[1]&&(t[0]=t[1])}function Al(t,e,i,n){var o=[];if(!t)return o;e[0]1e4)return[];return e[1]>(o.length?o[o.length-1]:i[1])&&o.push(e[1]),o}function Dl(t){return t.get("stack")||AA+t.seriesIndex}function Cl(t){return t.dim+t.index}function Ll(t){var e=[],i=t.axis;if("category"===i.type){for(var n=i.getBandWidth(),o=0;o=0?"p":"n",b=m;p&&(o[r][_]||(o[r][_]={p:m,n:m}),b=o[r][_][w]);var S,M,I,T;if(g)S=b,M=(A=i.dataToPoint([x,_]))[1]+l,I=A[0]-m,T=u,Math.abs(I)a[1]?(n=a[1],o=a[0]):(n=a[0],o=a[1]);var r=e.toGlobalCoord(e.dataToCoord(0));return ro&&(r=o),r}function Vl(t,e){return VA(t,BA(e))}function Gl(t,e){var i,n,o,a=t.type,r=e.getMin(),s=e.getMax(),l=null!=r,u=null!=s,h=t.getExtent();"ordinal"===a?i=e.getCategories().length:(y(n=e.get("boundaryGap"))||(n=[n||0,n||0]),"boolean"==typeof n[0]&&(n=[0,0]),n[0]=Vo(n[0],1),n[1]=Vo(n[1],1),o=h[1]-h[0]||Math.abs(h[0])),null==r&&(r="ordinal"===a?i?0:NaN:h[0]-n[0]*o),null==s&&(s="ordinal"===a?i?i-1:NaN:h[1]+n[1]*o),"dataMin"===r?r=h[0]:"function"==typeof r&&(r=r({min:h[0],max:h[1]})),"dataMax"===s?s=h[1]:"function"==typeof s&&(s=s({min:h[0],max:h[1]})),(null==r||!isFinite(r))&&(r=NaN),(null==s||!isFinite(s))&&(s=NaN),t.setBlank(I(r)||I(s)||"ordinal"===a&&!t.getOrdinalMeta().categories.length),e.getNeedCrossZero()&&(r>0&&s>0&&!l&&(r=0),r<0&&s<0&&!u&&(s=0));var c=e.ecModel;if(c&&"time"===a){var f,p=kl("bar",c);if(d(p,function(t){f|=t.getBaseAxis()===e.axis}),f){var g=Pl(p),m=Fl(r,s,e,g);r=m.min,s=m.max}}return[r,s]}function Fl(t,e,i,n){var o=i.axis.getExtent(),a=o[1]-o[0],r=Ol(n,i.axis);if(void 0===r)return{min:t,max:e};var s=1/0;d(r,function(t){s=Math.min(t.offset,s)});var l=-1/0;d(r,function(t){l=Math.max(t.offset+t.width,l)}),s=Math.abs(s),l=Math.abs(l);var u=s+l,h=e-t,c=h/(1-(s+l)/a)-h;return e+=c*(l/u),t-=c*(s/u),{min:t,max:e}}function Wl(t,e){var i=Gl(t,e),n=null!=e.getMin(),o=null!=e.getMax(),a=e.get("splitNumber");"log"===t.type&&(t.base=e.get("logBase"));var r=t.type;t.setExtent(i[0],i[1]),t.niceExtent({splitNumber:a,fixMin:n,fixMax:o,minInterval:"interval"===r||"time"===r?e.get("minInterval"):null,maxInterval:"interval"===r||"time"===r?e.get("maxInterval"):null});var s=e.get("interval");null!=s&&t.setInterval&&t.setInterval(s)}function Hl(t,e){if(e=e||t.get("type"))switch(e){case"category":return new SA(t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),[1/0,-1/0]);case"value":return new TA;default:return(xl.getClass(e)||TA).create(t)}}function Zl(t){var e=t.scale.getExtent(),i=e[0],n=e[1];return!(i>0&&n>0||i<0&&n<0)}function Ul(t){var e=t.getLabelModel().get("formatter"),i="category"===t.type?t.scale.getExtent()[0]:null;return"string"==typeof e?e=function(e){return function(i){return i=t.scale.getLabel(i),e.replace("{value}",null!=i?i:"")}}(e):"function"==typeof e?function(n,o){return null!=i&&(o=n-i),e(Xl(t,n),o)}:function(e){return t.scale.getLabel(e)}}function Xl(t,e){return"category"===t.type?t.scale.getLabel(e):e}function jl(t){var e=t.model,i=t.scale;if(e.get("axisLabel.show")&&!i.isBlank()){var n,o,a="category"===t.type,r=i.getExtent();o=a?i.count():(n=i.getTicks()).length;var s,l=t.getLabelModel(),u=Ul(t),h=1;o>40&&(h=Math.ceil(o/40));for(var c=0;c>1^-(1&s),l=l>>1^-(1&l),o=s+=o,a=l+=a,n.push([s/i,l/i])}return n}function ou(t){return"category"===t.type?ru(t):uu(t)}function au(t,e){return"category"===t.type?lu(t,e):{ticks:t.scale.getTicks()}}function ru(t){var e=t.getLabelModel(),i=su(t,e);return!e.get("show")||t.scale.isBlank()?{labels:[],labelCategoryInterval:i.labelCategoryInterval}:i}function su(t,e){var i=hu(t,"labels"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;return a=x(n)?vu(t,n):mu(t,r="auto"===n?fu(t):n),du(i,n,{labels:a,labelCategoryInterval:r})}function lu(t,e){var i=hu(t,"ticks"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;if(e.get("show")&&!t.scale.isBlank()||(a=[]),x(n))a=vu(t,n,!0);else if("auto"===n){var s=su(t,t.getLabelModel());r=s.labelCategoryInterval,a=f(s.labels,function(t){return t.tickValue})}else a=mu(t,r=n,!0);return du(i,n,{ticks:a,tickCategoryInterval:r})}function uu(t){var e=t.scale.getTicks(),i=Ul(t);return{labels:f(e,function(e,n){return{formattedLabel:i(e,n),rawLabel:t.scale.getLabel(e),tickValue:e}})}}function hu(t,e){return nD(t)[e]||(nD(t)[e]=[])}function cu(t,e){for(var i=0;i40&&(s=Math.max(1,Math.floor(r/40)));for(var l=a[0],u=t.dataToCoord(l+1)-t.dataToCoord(l),h=Math.abs(u*Math.cos(n)),c=Math.abs(u*Math.sin(n)),d=0,f=0;l<=a[1];l+=s){var p=0,g=0,m=ke(i(l),e.font,"center","top");p=1.3*m.width,g=1.3*m.height,d=Math.max(d,p,7),f=Math.max(f,g,7)}var v=d/h,y=f/c;isNaN(v)&&(v=1/0),isNaN(y)&&(y=1/0);var x=Math.max(0,Math.floor(Math.min(v,y))),_=nD(t.model),w=_.lastAutoInterval,b=_.lastTickCount;return null!=w&&null!=b&&Math.abs(w-x)<=1&&Math.abs(b-r)<=1&&w>x?x=w:(_.lastTickCount=r,_.lastAutoInterval=x),x}function gu(t){var e=t.getLabelModel();return{axisRotate:t.getRotate?t.getRotate():t.isHorizontal&&!t.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}function mu(t,e,i){function n(t){l.push(i?t:{formattedLabel:o(t),rawLabel:a.getLabel(t),tickValue:t})}var o=Ul(t),a=t.scale,r=a.getExtent(),s=t.getLabelModel(),l=[],u=Math.max((e||0)+1,1),h=r[0],c=a.count();0!==h&&u>1&&c/u>2&&(h=Math.round(Math.ceil(h/u)*u));var d=Kl(t),f=s.get("showMinLabel")||d,p=s.get("showMaxLabel")||d;f&&h!==r[0]&&n(r[0]);for(var g=h;g<=r[1];g+=u)n(g);return p&&g!==r[1]&&n(r[1]),l}function vu(t,e,i){var n=t.scale,o=Ul(t),a=[];return d(n.getTicks(),function(t){var r=n.getLabel(t);e(t,r)&&a.push(i?t:{formattedLabel:o(t),rawLabel:r,tickValue:t})}),a}function yu(t,e){var i=(t[1]-t[0])/e/2;t[0]+=i,t[1]-=i}function xu(t,e,i,n,o){function a(t,e){return h?t>e:t0&&(t.coord-=u/(2*(e+1)))}),s={coord:e[r-1].coord+u},e.push(s)}var h=l[0]>l[1];a(e[0].coord,l[0])&&(o?e[0].coord=l[0]:e.shift()),o&&a(l[0],e[0].coord)&&e.unshift({coord:l[0]}),a(l[1],s.coord)&&(o?s.coord=l[1]:e.pop()),o&&a(s.coord,l[1])&&e.push({coord:l[1]})}}function _u(t,e){var i=t.mapDimension("defaultedLabel",!0),n=i.length;if(1===n)return fr(t,e,i[0]);if(n){for(var o=[],a=0;a0?i=n[0]:n[1]<0&&(i=n[1]),i}function Ou(t,e,i,n){var o=NaN;t.stacked&&(o=i.get(i.getCalculationInfo("stackedOverDimension"),n)),isNaN(o)&&(o=t.valueStart);var a=t.baseDataOffset,r=[];return r[a]=i.get(t.baseDim,n),r[1-a]=o,e.dataToPoint(r)}function Eu(t,e){var i=[];return e.diff(t).add(function(t){i.push({cmd:"+",idx:t})}).update(function(t,e){i.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){i.push({cmd:"-",idx:t})}).execute(),i}function Ru(t){return isNaN(t[0])||isNaN(t[1])}function zu(t,e,i,n,o,a,r,s,l,u,h){return"none"!==u&&u?Bu.apply(this,arguments):Vu.apply(this,arguments)}function Bu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]);else if(l>0){var g=e[c],m="y"===u?1:0,v=(p[m]-g[m])*l;_D(bD,g),bD[m]=g[m]+v,_D(SD,p),SD[m]=p[m]-v,t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1])}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Vu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]),_D(bD,p);else if(l>0){var g=d+a,m=e[g];if(h)for(;m&&Ru(e[g]);)m=e[g+=a];var v=.5,y=e[c];if(!(m=e[g])||Ru(m))_D(SD,p);else{Ru(m)&&!h&&(m=p),U(wD,m,y);var x,_;if("x"===u||"y"===u){var w="x"===u?0:1;x=Math.abs(p[w]-y[w]),_=Math.abs(p[w]-m[w])}else x=uw(p,y),_=uw(p,m);xD(SD,p,wD,-l*(1-(v=_/(_+x))))}vD(bD,bD,s),yD(bD,bD,r),vD(SD,SD,s),yD(SD,SD,r),t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1]),xD(bD,p,wD,l*v)}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Gu(t,e){var i=[1/0,1/0],n=[-1/0,-1/0];if(e)for(var o=0;on[0]&&(n[0]=a[0]),a[1]>n[1]&&(n[1]=a[1])}return{min:e?i:n,max:e?n:i}}function Fu(t,e){if(t.length===e.length){for(var i=0;ie[0]?1:-1;e[0]+=n*i,e[1]-=n*i}return e}function Zu(t,e,i){if(!i.valueDim)return[];for(var n=[],o=0,a=e.count();oa[1]&&a.reverse();var r=o.getExtent(),s=Math.PI/180;i&&(a[0]-=.5,a[1]+=.5);var l=new hM({shape:{cx:Go(t.cx,1),cy:Go(t.cy,1),r0:Go(a[0],1),r:Go(a[1],1),startAngle:-r[0]*s,endAngle:-r[1]*s,clockwise:o.inverse}});return e&&(l.shape.endAngle=-r[0]*s,To(l,{shape:{endAngle:-r[1]*s}},n)),l}function ju(t,e,i,n){return"polar"===t.type?Xu(t,e,i,n):Uu(t,e,i,n)}function Yu(t,e,i){for(var n=e.getBaseAxis(),o="x"===n.dim||"radius"===n.dim?0:1,a=[],r=0;r=0;a--){var r=i[a].dimension,s=t.dimensions[r],l=t.getDimensionInfo(s);if("x"===(n=l&&l.coordDim)||"y"===n){o=i[a];break}}if(o){var u=e.getAxis(n),h=f(o.stops,function(t){return{coord:u.toGlobalCoord(u.dataToCoord(t.value)),color:t.color}}),c=h.length,p=o.outerColors.slice();c&&h[0].coord>h[c-1].coord&&(h.reverse(),p.reverse());var g=h[0].coord-10,m=h[c-1].coord+10,v=m-g;if(v<.001)return"transparent";d(h,function(t){t.offset=(t.coord-g)/v}),h.push({offset:c?h[c-1].offset:.5,color:p[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:p[0]||"transparent"});var y=new TM(0,0,0,0,h,!0);return y[n]=g,y[n+"2"]=m,y}}}function Ku(t,e,i){var n=t.get("showAllSymbol"),o="auto"===n;if(!n||o){var a=i.getAxesByScale("ordinal")[0];if(a&&(!o||!$u(a,e))){var r=e.mapDimension(a.dim),s={};return d(a.getViewLabels(),function(t){s[t.tickValue]=1}),function(t){return!s.hasOwnProperty(e.get(r,t))}}}}function $u(t,e){var i=t.getExtent(),n=Math.abs(i[1]-i[0])/t.scale.count();isNaN(n)&&(n=0);for(var o=e.count(),a=Math.max(1,Math.round(o/5)),r=0;rn)return!1;return!0}function Ju(t){return this._axes[t]}function Qu(t){LD.call(this,t)}function th(t,e){return e.type||(e.data?"category":"value")}function eh(t,e,i){return t.getCoordSysModel()===e}function ih(t,e,i){this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this._initCartesian(t,e,i),this.model=t}function nh(t,e,i,n){function o(t){return t.dim+"_"+t.index}i.getAxesOnZeroOf=function(){return a?[a]:[]};var a,r=t[e],s=i.model,l=s.get("axisLine.onZero"),u=s.get("axisLine.onZeroAxisIndex");if(l){if(null!=u)oh(r[u])&&(a=r[u]);else for(var h in r)if(r.hasOwnProperty(h)&&oh(r[h])&&!n[o(r[h])]){a=r[h];break}a&&(n[o(a)]=!0)}}function oh(t){return t&&"category"!==t.type&&"time"!==t.type&&Zl(t)}function ah(t,e){var i=t.getExtent(),n=i[0]+i[1];t.toGlobalCoord="x"===t.dim?function(t){return t+e}:function(t){return n-t+e},t.toLocalCoord="x"===t.dim?function(t){return t-e}:function(t){return n-t+e}}function rh(t,e){return f(VD,function(e){return t.getReferringComponents(e)[0]})}function sh(t){return"cartesian2d"===t.get("coordinateSystem")}function lh(t){var e={componentType:t.mainType,componentIndex:t.componentIndex};return e[t.mainType+"Index"]=t.componentIndex,e}function uh(t,e,i,n){var o,a,r=Xo(i-t.rotation),s=n[0]>n[1],l="start"===e&&!s||"start"!==e&&s;return jo(r-GD/2)?(a=l?"bottom":"top",o="center"):jo(r-1.5*GD)?(a=l?"top":"bottom",o="center"):(a="middle",o=r<1.5*GD&&r>GD/2?l?"left":"right":l?"right":"left"),{rotation:r,textAlign:o,textVerticalAlign:a}}function hh(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)}function ch(t,e,i){if(!Kl(t.axis)){var n=t.get("axisLabel.showMinLabel"),o=t.get("axisLabel.showMaxLabel");e=e||[],i=i||[];var a=e[0],r=e[1],s=e[e.length-1],l=e[e.length-2],u=i[0],h=i[1],c=i[i.length-1],d=i[i.length-2];!1===n?(dh(a),dh(u)):fh(a,r)&&(n?(dh(r),dh(h)):(dh(a),dh(u))),!1===o?(dh(s),dh(c)):fh(l,s)&&(o?(dh(l),dh(d)):(dh(s),dh(c)))}}function dh(t){t&&(t.ignore=!0)}function fh(t,e,i){var n=t&&t.getBoundingRect().clone(),o=e&&e.getBoundingRect().clone();if(n&&o){var a=_t([]);return Mt(a,a,-t.rotation),n.applyTransform(bt([],a,t.getLocalTransform())),o.applyTransform(bt([],a,e.getLocalTransform())),n.intersect(o)}}function ph(t){return"middle"===t||"center"===t}function gh(t,e,i){var n=e.axis;if(e.get("axisTick.show")&&!n.scale.isBlank()){for(var o=e.getModel("axisTick"),a=o.getModel("lineStyle"),s=o.get("length"),l=n.getTicksCoords(),u=[],h=[],c=t._transform,d=[],f=0;f=0||t===e}function Sh(t){var e=Mh(t);if(e){var i=e.axisPointerModel,n=e.axis.scale,o=i.option,a=i.get("status"),r=i.get("value");null!=r&&(r=n.parse(r));var s=Th(i);null==a&&(o.status=s?"show":"hide");var l=n.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==r||r>l[1])&&(r=l[1]),r0?"bottom":"top":o.width>0?"left":"right";l||kh(t.style,d,n,u,a,i,p),fo(t,d)}function Rh(t,e){var i=t.get(tC)||0;return Math.min(i,Math.abs(e.width),Math.abs(e.height))}function zh(t,e,i){var n=t.getData(),o=[],a=n.getLayout("valueAxisHorizontal")?1:0;o[1-a]=n.getLayout("valueAxisStart");var r=new nC({shape:{points:n.getLayout("largePoints")},incremental:!!i,__startPoint:o,__valueIdx:a});e.add(r),Bh(r,t,n)}function Bh(t,e,i){var n=i.getVisual("borderColor")||i.getVisual("color"),o=e.getModel("itemStyle").getItemStyle(["color","borderColor"]);t.useStyle(o),t.style.fill=null,t.style.stroke=n,t.style.lineWidth=i.getLayout("barWidth")}function Vh(t,e,i,n){var o=e.getData(),a=this.dataIndex,r=o.getName(a),s=e.get("selectedOffset");n.dispatchAction({type:"pieToggleSelect",from:t,name:r,seriesId:e.id}),o.each(function(t){Gh(o.getItemGraphicEl(t),o.getItemLayout(t),e.isSelected(o.getName(t)),s,i)})}function Gh(t,e,i,n,o){var a=(e.startAngle+e.endAngle)/2,r=Math.cos(a),s=Math.sin(a),l=i?n:0,u=[r*l,s*l];o?t.animate().when(200,{position:u}).start("bounceOut"):t.attr("position",u)}function Fh(t,e){function i(){a.ignore=a.hoverIgnore,r.ignore=r.hoverIgnore}function n(){a.ignore=a.normalIgnore,r.ignore=r.normalIgnore}tb.call(this);var o=new hM({z2:2}),a=new gM,r=new rM;this.add(o),this.add(a),this.add(r),this.updateData(t,e,!0),this.on("emphasis",i).on("normal",n).on("mouseover",i).on("mouseout",n)}function Wh(t,e,i,n,o,a,r){function s(e,i){for(var n=e;n>=0&&(t[n].y-=i,!(n>0&&t[n].y>t[n-1].y+t[n-1].height));n--);}function l(t,e,i,n,o,a){for(var r=e?Number.MAX_VALUE:0,s=0,l=t.length;s=r&&(d=r-10),!e&&d<=r&&(d=r+10),t[s].x=i+d*a,r=d}}t.sort(function(t,e){return t.y-e.y});for(var u,h=0,c=t.length,d=[],f=[],p=0;pe&&a+1t[a].y+t[a].height)return void s(a,n/2);s(i-1,n/2)}(p,c,-u),h=t[p].y+t[p].height;r-h<0&&s(c-1,h-r);for(p=0;p=i?f.push(t[p]):d.push(t[p]);l(d,!1,e,i,n,o),l(f,!0,e,i,n,o)}function Hh(t,e,i,n,o,a){for(var r=[],s=[],l=0;l3?1.4:o>1?1.2:1.1;hc(this,"zoom","zoomOnMouseWheel",t,{scale:n>0?s:1/s,originX:a,originY:r})}if(i){var l=Math.abs(n);hc(this,"scrollMove","moveOnMouseWheel",t,{scrollDelta:(n>0?1:-1)*(l>3?.4:l>1?.15:.05),originX:a,originY:r})}}}function uc(t){ic(this._zr,"globalPan")||hc(this,"zoom",null,t,{scale:t.pinchScale>1?1.1:1/1.1,originX:t.pinchX,originY:t.pinchY})}function hc(t,e,i,n,o){t.pointerChecker&&t.pointerChecker(n,o.originX,o.originY)&&(mw(n.event),cc(t,e,i,n,o))}function cc(t,e,i,n,o){o.isAvailableBehavior=m(dc,null,i,n),t.trigger(e,o)}function dc(t,e,i){var n=i[t];return!t||n&&(!_(n)||e.event[n+"Key"])}function fc(t,e,i){var n=t.target,o=n.position;o[0]+=e,o[1]+=i,n.dirty()}function pc(t,e,i,n){var o=t.target,a=t.zoomLimit,r=o.position,s=o.scale,l=t.zoom=t.zoom||1;if(l*=e,a){var u=a.min||0,h=a.max||1/0;l=Math.max(Math.min(h,l),u)}var c=l/t.zoom;t.zoom=l,r[0]-=(i-r[0])*(c-1),r[1]-=(n-r[1])*(c-1),s[0]*=c,s[1]*=c,o.dirty()}function gc(t,e,i){var n=e.getComponentByElement(t.topTarget),o=n&&n.coordinateSystem;return n&&n!==i&&!RC[n.mainType]&&o&&o.model!==i}function mc(t,e){var i=t.getItemStyle(),n=t.get("areaColor");return null!=n&&(i.fill=n),i}function vc(t,e,i,n,o){i.off("click"),i.off("mousedown"),e.get("selectedMode")&&(i.on("mousedown",function(){t._mouseDownFlag=!0}),i.on("click",function(a){if(t._mouseDownFlag){t._mouseDownFlag=!1;for(var r=a.target;!r.__regions;)r=r.parent;if(r){var s={type:("geo"===e.mainType?"geo":"map")+"ToggleSelect",batch:f(r.__regions,function(t){return{name:t.name,from:o.uid}})};s[e.mainType+"Id"]=e.id,n.dispatchAction(s),yc(e,i)}}}))}function yc(t,e){e.eachChild(function(e){d(e.__regions,function(i){e.trigger(t.isSelected(i.name)?"emphasis":"normal")})})}function xc(t,e){var i=new tb;this.uid=Ro("ec_map_draw"),this._controller=new oc(t.getZr()),this._controllerHost={target:e?i:null},this.group=i,this._updateGroup=e,this._mouseDownFlag,this._mapName,this._initialized,i.add(this._regionsGroup=new tb),i.add(this._backgroundGroup=new tb)}function _c(t){var e=this[zC];e&&e.recordVersion===this[BC]&&wc(e,t)}function wc(t,e){var i=t.circle,n=t.labelModel,o=t.hoverLabelModel,a=t.emphasisText,r=t.normalText;e?(i.style.extendFrom(mo({},o,{text:o.get("show")?a:null},{isRectText:!0,useInsideStyle:!1},!0)),i.__mapOriginalZ2=i.z2,i.z2+=NM):(mo(i.style,n,{text:n.get("show")?r:null,textPosition:n.getShallow("position")||"bottom"},{isRectText:!0,useInsideStyle:!1}),i.dirty(!1),null!=i.__mapOriginalZ2&&(i.z2=i.__mapOriginalZ2,i.__mapOriginalZ2=null))}function bc(t,e,i){var n=t.getZoom(),o=t.getCenter(),a=e.zoom,r=t.dataToPoint(o);if(null!=e.dx&&null!=e.dy){r[0]-=e.dx,r[1]-=e.dy;o=t.pointToData(r);t.setCenter(o)}if(null!=a){if(i){var s=i.min||0,l=i.max||1/0;a=Math.max(Math.min(n*a,l),s)/n}t.scale[0]*=a,t.scale[1]*=a;var u=t.position,h=(e.originX-u[0])*(a-1),c=(e.originY-u[1])*(a-1);u[0]-=h,u[1]-=c,t.updateTransform();o=t.pointToData(r);t.setCenter(o),t.setZoom(a*n)}return{center:t.getCenter(),zoom:t.getZoom()}}function Sc(){Tw.call(this)}function Mc(t){this.name=t,this.zoomLimit,Tw.call(this),this._roamTransformable=new Sc,this._rawTransformable=new Sc,this._center,this._zoom}function Ic(t,e,i,n){var o=i.seriesModel,a=o?o.coordinateSystem:null;return a===this?a[t](n):null}function Tc(t,e,i,n){Mc.call(this,t),this.map=e;var o=OC.load(e,i);this._nameCoordMap=o.nameCoordMap,this._regionsMap=o.regionsMap,this._invertLongitute=null==n||n,this.regions=o.regions,this._rect=o.boundingRect}function Ac(t,e,i,n){var o=i.geoModel,a=i.seriesModel,r=o?o.coordinateSystem:a?a.coordinateSystem||(a.getReferringComponents("geo")[0]||{}).coordinateSystem:null;return r===this?r[t](n):null}function Dc(t,e){var i=t.get("boundingCoords");if(null!=i){var n=i[0],o=i[1];isNaN(n[0])||isNaN(n[1])||isNaN(o[0])||isNaN(o[1])||this.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1])}var a,r=this.getBoundingRect(),s=t.get("layoutCenter"),l=t.get("layoutSize"),u=e.getWidth(),h=e.getHeight(),c=r.width/r.height*this.aspectScale,d=!1;s&&l&&(s=[Vo(s[0],u),Vo(s[1],h)],l=Vo(l,Math.min(u,h)),isNaN(s[0])||isNaN(s[1])||isNaN(l)||(d=!0));if(d){var f={};c>1?(f.width=l,f.height=l/c):(f.height=l,f.width=l*c),f.y=s[1]-f.height/2,f.x=s[0]-f.width/2}else(a=t.getBoxLayoutParams()).aspect=c,f=ca(a,{width:u,height:h});this.setViewRect(f.x,f.y,f.width,f.height),this.setCenter(t.get("center")),this.setZoom(t.get("zoom"))}function Cc(t,e){d(e.get("geoCoord"),function(e,i){t.addGeoCoord(i,e)})}function Lc(t,e){var i={};return d(t,function(t){t.each(t.mapDimension("value"),function(e,n){var o="ec-"+t.getName(n);i[o]=i[o]||[],isNaN(e)||i[o].push(e)})}),t[0].map(t[0].mapDimension("value"),function(n,o){for(var a="ec-"+t[0].getName(o),r=0,s=1/0,l=-1/0,u=i[a].length,h=0;h=0;o--){var a=i[o];a.hierNode={defaultAncestor:null,ancestor:a,prelim:0,modifier:0,change:0,shift:0,i:o,thread:null},n.push(a)}}function Wc(t,e){var i=t.isExpand?t.children:[],n=t.parentNode.children,o=t.hierNode.i?n[t.hierNode.i-1]:null;if(i.length){jc(t);var a=(i[0].hierNode.prelim+i[i.length-1].hierNode.prelim)/2;o?(t.hierNode.prelim=o.hierNode.prelim+e(t,o),t.hierNode.modifier=t.hierNode.prelim-a):t.hierNode.prelim=a}else o&&(t.hierNode.prelim=o.hierNode.prelim+e(t,o));t.parentNode.hierNode.defaultAncestor=Yc(t,o,t.parentNode.hierNode.defaultAncestor||n[0],e)}function Hc(t){var e=t.hierNode.prelim+t.parentNode.hierNode.modifier;t.setLayout({x:e},!0),t.hierNode.modifier+=t.parentNode.hierNode.modifier}function Zc(t){return arguments.length?t:Qc}function Uc(t,e){var i={};return t-=Math.PI/2,i.x=e*Math.cos(t),i.y=e*Math.sin(t),i}function Xc(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}function jc(t){for(var e=t.children,i=e.length,n=0,o=0;--i>=0;){var a=e[i];a.hierNode.prelim+=n,a.hierNode.modifier+=n,o+=a.hierNode.change,n+=a.hierNode.shift+o}}function Yc(t,e,i,n){if(e){for(var o=t,a=t,r=a.parentNode.children[0],s=e,l=o.hierNode.modifier,u=a.hierNode.modifier,h=r.hierNode.modifier,c=s.hierNode.modifier;s=qc(s),a=Kc(a),s&&a;){o=qc(o),r=Kc(r),o.hierNode.ancestor=t;var d=s.hierNode.prelim+c-a.hierNode.prelim-u+n(s,a);d>0&&(Jc($c(s,t,i),t,d),u+=d,l+=d),c+=s.hierNode.modifier,u+=a.hierNode.modifier,l+=o.hierNode.modifier,h+=r.hierNode.modifier}s&&!qc(o)&&(o.hierNode.thread=s,o.hierNode.modifier+=c-l),a&&!Kc(r)&&(r.hierNode.thread=a,r.hierNode.modifier+=u-h,i=t)}return i}function qc(t){var e=t.children;return e.length&&t.isExpand?e[e.length-1]:t.hierNode.thread}function Kc(t){var e=t.children;return e.length&&t.isExpand?e[0]:t.hierNode.thread}function $c(t,e,i){return t.hierNode.ancestor.parentNode===e.parentNode?t.hierNode.ancestor:i}function Jc(t,e,i){var n=i/(e.hierNode.i-t.hierNode.i);e.hierNode.change-=n,e.hierNode.shift+=i,e.hierNode.modifier+=i,e.hierNode.prelim+=i,t.hierNode.change+=n}function Qc(t,e){return t.parentNode===e.parentNode?1:2}function td(t,e){var i=t.getItemLayout(e);return i&&!isNaN(i.x)&&!isNaN(i.y)&&"none"!==t.getItemVisual(e,"symbol")}function ed(t,e,i){return i.itemModel=e,i.itemStyle=e.getModel("itemStyle").getItemStyle(),i.hoverItemStyle=e.getModel("emphasis.itemStyle").getItemStyle(),i.lineStyle=e.getModel("lineStyle").getLineStyle(),i.labelModel=e.getModel("label"),i.hoverLabelModel=e.getModel("emphasis.label"),!1===t.isExpand&&0!==t.children.length?i.symbolInnerColor=i.itemStyle.fill:i.symbolInnerColor="#fff",i}function id(t,e,i,n,o,a){var s=!i,l=t.tree.getNodeByDataIndex(e),a=ed(l,l.getModel(),a),u=t.tree.root,h=l.parentNode===u?l:l.parentNode||l,c=t.getItemGraphicEl(h.dataIndex),d=h.getLayout(),f=c?{x:c.position[0],y:c.position[1],rawX:c.__radialOldRawX,rawY:c.__radialOldRawY}:d,p=l.getLayout();s?(i=new wu(t,e,a)).attr("position",[f.x,f.y]):i.updateData(t,e,a),i.__radialOldRawX=i.__radialRawX,i.__radialOldRawY=i.__radialRawY,i.__radialRawX=p.rawX,i.__radialRawY=p.rawY,n.add(i),t.setItemGraphicEl(e,i),Io(i,{position:[p.x,p.y]},o);var g=i.getSymbolPath();if("radial"===a.layout){var m,v,y=u.children[0],x=y.getLayout(),_=y.children.length;if(p.x===x.x&&!0===l.isExpand){var w={};w.x=(y.children[0].getLayout().x+y.children[_-1].getLayout().x)/2,w.y=(y.children[0].getLayout().y+y.children[_-1].getLayout().y)/2,(m=Math.atan2(w.y-x.y,w.x-x.x))<0&&(m=2*Math.PI+m),(v=w.xx.x)||(m-=Math.PI);var b=v?"left":"right";g.setStyle({textPosition:b,textRotation:-m,textOrigin:"center",verticalAlign:"middle"})}if(l.parentNode&&l.parentNode!==u){var S=i.__edge;S||(S=i.__edge=new bM({shape:od(a,f,f),style:r({opacity:0,strokeNoScale:!0},a.lineStyle)})),Io(S,{shape:od(a,d,p),style:{opacity:1}},o),n.add(S)}}function nd(t,e,i,n,o,a){for(var r,s=t.tree.getNodeByDataIndex(e),l=t.tree.root,a=ed(s,s.getModel(),a),u=s.parentNode===l?s:s.parentNode||s;null==(r=u.getLayout());)u=u.parentNode===l?u:u.parentNode||u;Io(i,{position:[r.x+1,r.y+1]},o,function(){n.remove(i),t.setItemGraphicEl(e,null)}),i.fadeOut(null,{keepLabel:!0});var h=i.__edge;h&&Io(h,{shape:od(a,r,r),style:{opacity:0}},o,function(){n.remove(h)})}function od(t,e,i){var n,o,a,r,s,l,u,h,c=t.orient;if("radial"===t.layout){s=e.rawX,u=e.rawY,l=i.rawX,h=i.rawY;var d=Uc(s,u),f=Uc(s,u+(h-u)*t.curvature),p=Uc(l,h+(u-h)*t.curvature),g=Uc(l,h);return{x1:d.x,y1:d.y,x2:g.x,y2:g.y,cpx1:f.x,cpy1:f.y,cpx2:p.x,cpy2:p.y}}return s=e.x,u=e.y,l=i.x,h=i.y,"LR"!==c&&"RL"!==c||(n=s+(l-s)*t.curvature,o=u,a=l+(s-l)*t.curvature,r=h),"TB"!==c&&"BT"!==c||(n=s,o=u+(h-u)*t.curvature,a=l,r=h+(u-h)*t.curvature),{x1:s,y1:u,x2:l,y2:h,cpx1:n,cpy1:o,cpx2:a,cpy2:r}}function ad(t,e,i){for(var n,o=[t],a=[];n=o.pop();)if(a.push(n),n.isExpand){var r=n.children;if(r.length)for(var s=0;s=0;a--)n.push(o[a])}}function sd(t,e){var i=Xc(t,e);t.layoutInfo=i;var n=t.get("layout"),o=0,a=0,r=null;"radial"===n?(o=2*Math.PI,a=Math.min(i.height,i.width)/2,r=Zc(function(t,e){return(t.parentNode===e.parentNode?1:2)/t.depth})):(o=i.width,a=i.height,r=Zc());var s=t.getData().tree.root,l=s.children[0];if(l){Fc(s),ad(l,Wc,r),s.hierNode.modifier=-l.hierNode.prelim,rd(l,Hc);var u=l,h=l,c=l;rd(l,function(t){var e=t.getLayout().x;eh.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)});var d=u===h?1:r(u,h)/2,f=d-u.getLayout().x,p=0,g=0,m=0,v=0;if("radial"===n)p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v=(t.depth-1)*g;var e=Uc(m,v);t.setLayout({x:e.x,y:e.y,rawX:m,rawY:v},!0)});else{var y=t.getOrient();"RL"===y||"LR"===y?(g=a/(h.getLayout().x+d+f),p=o/(c.depth-1||1),rd(l,function(t){v=(t.getLayout().x+f)*g,m="LR"===y?(t.depth-1)*p:o-(t.depth-1)*p,t.setLayout({x:m,y:v},!0)})):"TB"!==y&&"BT"!==y||(p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v="TB"===y?(t.depth-1)*g:a-(t.depth-1)*g,t.setLayout({x:m,y:v},!0)}))}}}function ld(t,e,i){if(t&&l(e,t.type)>=0){var n=i.getData().tree.root,o=t.targetNode;if("string"==typeof o&&(o=n.getNodeById(o)),o&&n.contains(o))return{node:o};var a=t.targetNodeId;if(null!=a&&(o=n.getNodeById(a)))return{node:o}}}function ud(t){for(var e=[];t;)(t=t.parentNode)&&e.push(t);return e.reverse()}function hd(t,e){return l(ud(t),e)>=0}function cd(t,e){for(var i=[];t;){var n=t.dataIndex;i.push({name:t.name,dataIndex:n,value:e.getRawValue(n)}),t=t.parentNode}return i.reverse(),i}function dd(t){var e=0;d(t.children,function(t){dd(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function fd(t,e){var i=e.get("color");if(i){var n;return d(t=t||[],function(t){var e=new No(t),i=e.get("color");(e.get("itemStyle.color")||i&&"none"!==i)&&(n=!0)}),n||((t[0]||(t[0]={})).color=i.slice()),t}}function pd(t){this.group=new tb,t.add(this.group)}function gd(t,e,i,n,o,a){var r=[[o?t:t-UC,e],[t+i,e],[t+i,e+n],[o?t:t-UC,e+n]];return!a&&r.splice(2,0,[t+i+UC,e+n/2]),!o&&r.push([t,e+n/2]),r}function md(t,e,i){t.eventData={componentType:"series",componentSubType:"treemap",componentIndex:e.componentIndex,seriesIndex:e.componentIndex,seriesName:e.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:i&&i.dataIndex,name:i&&i.name},treePathInfo:i&&cd(i,e)}}function vd(){var t,e=[],i={};return{add:function(t,n,o,a,r){return _(a)&&(r=a,a=0),!i[t.id]&&(i[t.id]=1,e.push({el:t,target:n,time:o,delay:a,easing:r}),!0)},done:function(e){return t=e,this},start:function(){for(var n=e.length,o=0,a=e.length;o=0;a--)null==i[a]&&(delete n[e[a]],e.pop())}function bd(t,e){var i=t.visual,n=[];w(i)?sL(i,function(t){n.push(t)}):null!=i&&n.push(i);var o={color:1,symbol:1};e||1!==n.length||o.hasOwnProperty(t.type)||(n[1]=n[0]),Ld(t,n)}function Sd(t){return{applyVisual:function(e,i,n){e=this.mapValueToVisual(e),n("color",t(i("color"),e))},_doMap:Dd([0,1])}}function Md(t){var e=this.option.visual;return e[Math.round(Bo(t,[0,1],[0,e.length-1],!0))]||{}}function Id(t){return function(e,i,n){n(t,this.mapValueToVisual(e))}}function Td(t){var e=this.option.visual;return e[this.option.loop&&t!==uL?t%e.length:t]}function Ad(){return this.option.visual[0]}function Dd(t){return{linear:function(e){return Bo(e,t,this.option.visual,!0)},category:Td,piecewise:function(e,i){var n=Cd.call(this,i);return null==n&&(n=Bo(e,t,this.option.visual,!0)),n},fixed:Ad}}function Cd(t){var e=this.option,i=e.pieceList;if(e.hasSpecialVisual){var n=i[hL.findPieceIndex(t,i)];if(n&&n.visual)return n.visual[this.type]}}function Ld(t,e){return t.visual=e,"color"===t.type&&(t.parsedVisual=f(e,function(t){return Gt(t)})),e}function kd(t,e,i){return t?e<=i:e=o.length||t===o[t.depth])&&Pd(t,Vd(r,h,t,e,g,a),i,n,o,a)})}else l=Od(h),t.setVisual("color",l)}}function Nd(t,e,i,n){var o=a({},e);return d(["color","colorAlpha","colorSaturation"],function(a){var r=t.get(a,!0);null==r&&i&&(r=i[a]),null==r&&(r=e[a]),null==r&&(r=n.get(a)),null!=r&&(o[a]=r)}),o}function Od(t){var e=Rd(t,"color");if(e){var i=Rd(t,"colorAlpha"),n=Rd(t,"colorSaturation");return n&&(e=jt(e,null,null,n)),i&&(e=Yt(e,i)),e}}function Ed(t,e){return null!=e?jt(e,null,null,t):null}function Rd(t,e){var i=t[e];if(null!=i&&"none"!==i)return i}function zd(t,e,i,n,o,a){if(a&&a.length){var r=Bd(e,"color")||null!=o.color&&"none"!==o.color&&(Bd(e,"colorAlpha")||Bd(e,"colorSaturation"));if(r){var s=e.get("visualMin"),l=e.get("visualMax"),u=i.dataExtent.slice();null!=s&&su[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:r.name,dataExtent:u,visual:r.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var d=new hL(c);return d.__drColorMappingBy=h,d}}}function Bd(t,e){var i=t.get(e);return fL(i)&&i.length?{name:e,range:i}:null}function Vd(t,e,i,n,o,r){var s=a({},e);if(o){var l=o.type,u="color"===l&&o.__drColorMappingBy,h="index"===u?n:"id"===u?r.mapIdToIndex(i.getId()):i.getValue(t.get("visualDimension"));s[l]=o.mapValueToVisual(h)}return s}function Gd(t,e,i,n){var o,a;if(!t.isRemoved()){var r=t.getLayout();o=r.width,a=r.height;var s=(f=t.getModel()).get(_L),l=f.get(wL)/2,u=Kd(f),h=Math.max(s,u),c=s-l,d=h-l,f=t.getModel();t.setLayout({borderWidth:s,upperHeight:h,upperLabelHeight:u},!0);var p=(o=mL(o-2*c,0))*(a=mL(a-c-d,0)),g=Fd(t,f,p,e,i,n);if(g.length){var m={x:c,y:d,width:o,height:a},v=vL(o,a),y=1/0,x=[];x.area=0;for(var _=0,w=g.length;_=0;l--){var u=o["asc"===n?r-l-1:l].getValue();u/i*es[1]&&(s[1]=e)})}else s=[NaN,NaN];return{sum:n,dataExtent:s}}function Ud(t,e,i){for(var n,o=0,a=1/0,r=0,s=t.length;ro&&(o=n));var l=t.area*t.area,u=e*e*i;return l?mL(u*o/l,l/(u*a)):1/0}function Xd(t,e,i,n,o){var a=e===i.width?0:1,r=1-a,s=["x","y"],l=["width","height"],u=i[s[a]],h=e?t.area/e:0;(o||h>i[l[r]])&&(h=i[l[r]]);for(var c=0,d=t.length;cXM&&(u=XM),a=s}u=0?n+=u:n-=u:p>=0?n-=u:n+=u}return n}function pf(t,e){return t.getVisual("opacity")||t.getModel().get(e)}function gf(t,e,i){var n=t.getGraphicEl(),o=pf(t,e);null!=i&&(null==o&&(o=1),o*=i),n.downplay&&n.downplay(),n.traverse(function(t){if("group"!==t.type){var e=t.lineLabelOriginalOpacity;null!=e&&null==i||(e=o),t.setStyle("opacity",e)}})}function mf(t,e){var i=pf(t,e),n=t.getGraphicEl();n.highlight&&n.highlight(),n.traverse(function(t){"group"!==t.type&&t.setStyle("opacity",i)})}function vf(t){return t instanceof Array||(t=[t,t]),t}function yf(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=t.getGraph();i.eachNode(function(t){var e=t.getModel();t.setLayout([+e.get("x"),+e.get("y")])}),xf(i)}}function xf(t){t.eachEdge(function(t){var e=t.getModel().get("lineStyle.curveness")||0,i=F(t.node1.getLayout()),n=F(t.node2.getLayout()),o=[i,n];+e&&o.push([(i[0]+n[0])/2-(i[1]-n[1])*e,(i[1]+n[1])/2-(n[0]-i[0])*e]),t.setLayout(o)})}function _f(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=e.getBoundingRect(),n=t.getData(),o=n.graph,a=0,r=n.getSum("value"),s=2*Math.PI/(r||n.count()),l=i.width/2+i.x,u=i.height/2+i.y,h=Math.min(i.width,i.height)/2;o.eachNode(function(t){var e=t.getValue("value");a+=s*(r?e:1)/2,t.setLayout([h*Math.cos(a)+l,h*Math.sin(a)+u]),a+=s*(r?e:1)/2}),n.setLayout({cx:l,cy:u}),o.eachEdge(function(t){var e,i=t.getModel().get("lineStyle.curveness")||0,n=F(t.node1.getLayout()),o=F(t.node2.getLayout()),a=(n[0]+o[0])/2,r=(n[1]+o[1])/2;+i&&(e=[l*(i*=3)+a*(1-i),u*i+r*(1-i)]),t.setLayout([n,o,e])})}}function wf(t,e,i){for(var n=i.rect,o=n.width,a=n.height,r=[n.x+o/2,n.y+a/2],s=null==i.gravity?.1:i.gravity,l=0;l0?-1:i<0?1:e?-1:1}}function Pf(t,e){return Math.min(e[1],Math.max(e[0],t))}function Nf(t,e,i){this._axesMap=R(),this._axesLayout={},this.dimensions=t.dimensions,this._rect,this._model=t,this._init(t,e,i)}function Of(t,e){return ek(ik(t,e[0]),e[1])}function Ef(t,e){var i=e.layoutLength/(e.axisCount-1);return{position:i*t,axisNameAvailableWidth:i,axisLabelShow:!0}}function Rf(t,e){var i,n,o=e.layoutLength,a=e.axisExpandWidth,r=e.axisCount,s=e.axisCollapseWidth,l=e.winInnerIndices,u=s,h=!1;return tmk}function $f(t){var e=t.length-1;return e<0&&(e=0),[t[0],t[e]]}function Jf(t,e,i,n){var o=new tb;return o.add(new yM({name:"main",style:ip(i),silent:!0,draggable:!0,cursor:"move",drift:uk(t,e,o,"nswe"),ondragend:uk(qf,e,{isEnd:!0})})),hk(n,function(i){o.add(new yM({name:i,style:{opacity:0},draggable:!0,silent:!0,invisible:!0,drift:uk(t,e,o,i),ondragend:uk(qf,e,{isEnd:!0})}))}),o}function Qf(t,e,i,n){var o=n.brushStyle.lineWidth||0,a=fk(o,vk),r=i[0][0],s=i[1][0],l=r-o/2,u=s-o/2,h=i[0][1],c=i[1][1],d=h-a+o/2,f=c-a+o/2,p=h-r,g=c-s,m=p+o,v=g+o;ep(t,e,"main",r,s,p,g),n.transformable&&(ep(t,e,"w",l,u,a,v),ep(t,e,"e",d,u,a,v),ep(t,e,"n",l,u,m,a),ep(t,e,"s",l,f,m,a),ep(t,e,"nw",l,u,a,a),ep(t,e,"ne",d,u,a,a),ep(t,e,"sw",l,f,a,a),ep(t,e,"se",d,f,a,a))}function tp(t,e){var i=e.__brushOption,n=i.transformable,o=e.childAt(0);o.useStyle(ip(i)),o.attr({silent:!n,cursor:n?"move":"default"}),hk(["w","e","n","s","se","sw","ne","nw"],function(i){var o=e.childOfName(i),a=ap(t,i);o&&o.attr({silent:!n,invisible:!n,cursor:n?_k[a]+"-resize":null})})}function ep(t,e,i,n,o,a,r){var s=e.childOfName(i);s&&s.setShape(hp(up(t,e,[[n,o],[n+a,o+r]])))}function ip(t){return r({strokeNoScale:!0},t.brushStyle)}function np(t,e,i,n){var o=[dk(t,i),dk(e,n)],a=[fk(t,i),fk(e,n)];return[[o[0],a[0]],[o[1],a[1]]]}function op(t){return Ao(t.group)}function ap(t,e){if(e.length>1)return("e"===(n=[ap(t,(e=e.split(""))[0]),ap(t,e[1])])[0]||"w"===n[0])&&n.reverse(),n.join("");var i={left:"w",right:"e",top:"n",bottom:"s"},n=Co({w:"left",e:"right",n:"top",s:"bottom"}[e],op(t));return i[n]}function rp(t,e,i,n,o,a,r,s){var l=n.__brushOption,u=t(l.range),h=lp(i,a,r);hk(o.split(""),function(t){var e=xk[t];u[e[0]][e[1]]+=h[e[0]]}),l.range=e(np(u[0][0],u[1][0],u[0][1],u[1][1])),Zf(i,n),qf(i,{isEnd:!1})}function sp(t,e,i,n,o){var a=e.__brushOption.range,r=lp(t,i,n);hk(a,function(t){t[0]+=r[0],t[1]+=r[1]}),Zf(t,e),qf(t,{isEnd:!1})}function lp(t,e,i){var n=t.group,o=n.transformCoordToLocal(e,i),a=n.transformCoordToLocal(0,0);return[o[0]-a[0],o[1]-a[1]]}function up(t,e,n){var o=jf(t,e);return o&&!0!==o?o.clipPath(n,t._transform):i(n)}function hp(t){var e=dk(t[0][0],t[1][0]),i=dk(t[0][1],t[1][1]);return{x:e,y:i,width:fk(t[0][0],t[1][0])-e,height:fk(t[0][1],t[1][1])-i}}function cp(t,e,i){if(t._brushType){var n=t._zr,o=t._covers,a=Xf(t,e,i);if(!t._dragging)for(var r=0;r0;a--)Yp(s,l*=.99,r),jp(s,o,i,n,r),tg(s,l,r),jp(s,o,i,n,r)}function Up(t,e){var i=[],n="vertical"===e?"y":"x",o=Zi(t,function(t){return t.getLayout()[n]});return o.keys.sort(function(t,e){return t-e}),d(o.keys,function(t){i.push(o.buckets.get(t))}),i}function Xp(t,e,i,n,o,a,r){var s=[];d(e,function(t){var e=t.length,i=0,l=0;d(t,function(t){i+=t.getLayout().value}),l="vertical"===r?(o-(e-1)*a)/i:(n-(e-1)*a)/i,s.push(l)}),s.sort(function(t,e){return t-e});var l=s[0];d(e,function(t){d(t,function(t,e){var i=t.getLayout().value*l;"vertical"===r?(t.setLayout({x:e},!0),t.setLayout({dx:i},!0)):(t.setLayout({y:e},!0),t.setLayout({dy:i},!0))})}),d(i,function(t){var e=+t.getValue()*l;t.setLayout({dy:e},!0)})}function jp(t,e,i,n,o){d(t,function(t){var a,r,s,l=0,u=t.length;if("vertical"===o){var h;for(t.sort(function(t,e){return t.getLayout().x-e.getLayout().x}),s=0;s0&&(h=a.getLayout().x+r,a.setLayout({x:h},!0)),l=a.getLayout().x+a.getLayout().dx+e;if((r=l-e-n)>0)for(h=a.getLayout().x-r,a.setLayout({x:h},!0),l=h,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().x+a.getLayout().dx+e-l)>0&&(h=a.getLayout().x-r,a.setLayout({x:h},!0)),l=a.getLayout().x}else{var c;for(t.sort(function(t,e){return t.getLayout().y-e.getLayout().y}),s=0;s0&&(c=a.getLayout().y+r,a.setLayout({y:c},!0)),l=a.getLayout().y+a.getLayout().dy+e;if((r=l-e-i)>0)for(c=a.getLayout().y-r,a.setLayout({y:c},!0),l=c,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().y+a.getLayout().dy+e-l)>0&&(c=a.getLayout().y-r,a.setLayout({y:c},!0)),l=a.getLayout().y}})}function Yp(t,e,i){d(t.slice().reverse(),function(t){d(t,function(t){if(t.outEdges.length){var n=Qp(t.outEdges,qp,i)/Qp(t.outEdges,Jp,i);if("vertical"===i){var o=t.getLayout().x+(n-$p(t,i))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(n-$p(t,i))*e;t.setLayout({y:a},!0)}}})})}function qp(t,e){return $p(t.node2,e)*t.getValue()}function Kp(t,e){return $p(t.node1,e)*t.getValue()}function $p(t,e){return"vertical"===e?t.getLayout().x+t.getLayout().dx/2:t.getLayout().y+t.getLayout().dy/2}function Jp(t){return t.getValue()}function Qp(t,e,i){for(var n=0,o=t.length,a=-1;++a0?"P":"N",a=n.getVisual("borderColor"+o)||n.getVisual("color"+o),r=i.getModel(Gk).getItemStyle(Wk);e.useStyle(r),e.style.fill=null,e.style.stroke=a}function fg(t,e,i,n,o){return i>n?-1:i0?t.get(o,e-1)<=n?1:-1:1}function pg(t,e){var i,n=t.getBaseAxis(),o="category"===n.type?n.getBandWidth():(i=n.getExtent(),Math.abs(i[1]-i[0])/e.count()),a=Vo(A(t.get("barMaxWidth"),o),o),r=Vo(A(t.get("barMinWidth"),1),o),s=t.get("barWidth");return null!=s?Vo(s,o):Math.max(Math.min(o/2,a),r)}function gg(t){return y(t)||(t=[+t,+t]),t}function mg(t,e){t.eachChild(function(t){t.attr({z:e.z,zlevel:e.zlevel,style:{stroke:"stroke"===e.brushType?e.color:null,fill:"fill"===e.brushType?e.color:null}})})}function vg(t,e){tb.call(this);var i=new wu(t,e),n=new tb;this.add(i),this.add(n),n.beforeUpdate=function(){this.attr(i.getScale())},this.updateData(t,e)}function yg(t){var e=t.data;e&&e[0]&&e[0][0]&&e[0][0].coord&&(t.data=f(e,function(t){var e={coords:[t[0].coord,t[1].coord]};return t[0].name&&(e.fromName=t[0].name),t[1].name&&(e.toName=t[1].name),o([e,t[0],t[1]])}))}function xg(t,e,i){tb.call(this),this.add(this.createLine(t,e,i)),this._updateEffectSymbol(t,e)}function _g(t,e,i){tb.call(this),this._createPolyline(t,e,i)}function wg(t,e,i){xg.call(this,t,e,i),this._lastFrame=0,this._lastFramePercent=0}function bg(){this.group=new tb}function Sg(t){return t instanceof Array||(t=[t,t]),t}function Mg(){var t=iw();this.canvas=t,this.blurSize=30,this.pointSize=20,this.maxOpacity=1,this.minOpacity=0,this._gradientPixels={}}function Ig(t,e,i){var n=t[1]-t[0],o=(e=f(e,function(e){return{interval:[(e.interval[0]-t[0])/n,(e.interval[1]-t[0])/n]}})).length,a=0;return function(t){for(n=a;n=0;n--){var r=e[n].interval;if(r[0]<=t&&t<=r[1]){a=n;break}}return n>=0&&n=e[0]&&t<=e[1]}}function Ag(t){var e=t.dimensions;return"lng"===e[0]&&"lat"===e[1]}function Dg(t,e,i,n){var o=t.getItemLayout(e),a=i.get("symbolRepeat"),r=i.get("symbolClip"),s=i.get("symbolPosition")||"start",l=(i.get("symbolRotate")||0)*Math.PI/180||0,u=i.get("symbolPatternSize")||2,h=i.isAnimationEnabled(),c={dataIndex:e,layout:o,itemModel:i,symbolType:t.getItemVisual(e,"symbol")||"circle",color:t.getItemVisual(e,"color"),symbolClip:r,symbolRepeat:a,symbolRepeatDirection:i.get("symbolRepeatDirection"),symbolPatternSize:u,rotation:l,animationModel:h?i:null,hoverAnimation:h&&i.get("hoverAnimation"),z2:i.getShallow("z",!0)||0};Cg(i,a,o,n,c),kg(t,e,o,a,r,c.boundingLength,c.pxSign,u,n,c),Pg(i,c.symbolScale,l,n,c);var d=c.symbolSize,f=i.get("symbolOffset");return y(f)&&(f=[Vo(f[0],d[0]),Vo(f[1],d[1])]),Ng(i,d,o,a,r,f,s,c.valueLineWidth,c.boundingLength,c.repeatCutLength,n,c),c}function Cg(t,e,i,n,o){var a,r=n.valueDim,s=t.get("symbolBoundingData"),l=n.coordSys.getOtherAxis(n.coordSys.getBaseAxis()),u=l.toGlobalCoord(l.dataToCoord(0)),h=1-+(i[r.wh]<=0);if(y(s)){var c=[Lg(l,s[0])-u,Lg(l,s[1])-u];c[1]0?1:a<0?-1:0}function Lg(t,e){return t.toGlobalCoord(t.dataToCoord(t.scale.parse(e)))}function kg(t,e,i,n,o,a,r,s,l,u){var h=l.valueDim,c=l.categoryDim,d=Math.abs(i[c.wh]),f=t.getItemVisual(e,"symbolSize");y(f)?f=f.slice():(null==f&&(f="100%"),f=[f,f]),f[c.index]=Vo(f[c.index],d),f[h.index]=Vo(f[h.index],n?d:Math.abs(a)),u.symbolSize=f,(u.symbolScale=[f[0]/s,f[1]/s])[h.index]*=(l.isHorizontal?-1:1)*r}function Pg(t,e,i,n,o){var a=t.get(cP)||0;a&&(fP.attr({scale:e.slice(),rotation:i}),fP.updateTransform(),a/=fP.getLineScale(),a*=e[n.valueDim.index]),o.valueLineWidth=a}function Ng(t,e,i,n,o,r,s,l,u,h,c,d){var f=c.categoryDim,p=c.valueDim,g=d.pxSign,m=Math.max(e[p.index]+l,0),v=m;if(n){var y=Math.abs(u),x=T(t.get("symbolMargin"),"15%")+"",_=!1;x.lastIndexOf("!")===x.length-1&&(_=!0,x=x.slice(0,x.length-1)),x=Vo(x,e[p.index]);var w=Math.max(m+2*x,0),b=_?0:2*x,S=Qo(n),M=S?n:Kg((y+b)/w);w=m+2*(x=(y-M*m)/2/(_?M:M-1)),b=_?0:2*x,S||"fixed"===n||(M=h?Kg((Math.abs(h)+b)/w):0),v=M*w-b,d.repeatTimes=M,d.symbolMargin=x}var I=g*(v/2),A=d.pathPosition=[];A[f.index]=i[f.wh]/2,A[p.index]="start"===s?I:"end"===s?u-I:u/2,r&&(A[0]+=r[0],A[1]+=r[1]);var D=d.bundlePosition=[];D[f.index]=i[f.xy],D[p.index]=i[p.xy];var C=d.barRectShape=a({},i);C[p.wh]=g*Math.max(Math.abs(i[p.wh]),Math.abs(A[p.index]+I)),C[f.wh]=i[f.wh];var L=d.clipShape={};L[f.xy]=-i[f.xy],L[f.wh]=c.ecSize[f.wh],L[p.xy]=0,L[p.wh]=i[p.wh]}function Og(t){var e=t.symbolPatternSize,i=Jl(t.symbolType,-e/2,-e/2,e,e,t.color);return i.attr({culling:!0}),"image"!==i.type&&i.setStyle({strokeNoScale:!0}),i}function Eg(t,e,i,n){function o(t){var e=l.slice(),n=i.pxSign,o=t;return("start"===i.symbolRepeatDirection?n>0:n<0)&&(o=h-1-t),e[u.index]=d*(o-h/2+.5)+l[u.index],{position:e,scale:i.symbolScale.slice(),rotation:i.rotation}}var a=t.__pictorialBundle,r=i.symbolSize,s=i.valueLineWidth,l=i.pathPosition,u=e.valueDim,h=i.repeatTimes||0,c=0,d=r[e.valueDim.index]+s+2*i.symbolMargin;for(jg(t,function(t){t.__pictorialAnimationIndex=c,t.__pictorialRepeatTimes=h,c0)],d=t.__pictorialBarRect;kh(d.style,h,a,n,e.seriesModel,o,c),fo(d,h)}function Kg(t){var e=Math.round(t);return Math.abs(t-e)<1e-4?e:Math.ceil(t)}function $g(t,e,i){this.dimension="single",this.dimensions=["single"],this._axis=null,this._rect,this._init(t,e,i),this.model=t}function Jg(t,e){e=e||{};var i=t.coordinateSystem,n=t.axis,o={},a=n.position,r=n.orient,s=i.getRect(),l=[s.x,s.x+s.width,s.y,s.y+s.height],u={horizontal:{top:l[2],bottom:l[3]},vertical:{left:l[0],right:l[1]}};o.position=["vertical"===r?u.vertical[a]:l[0],"horizontal"===r?u.horizontal[a]:l[3]];var h={horizontal:0,vertical:1};o.rotation=Math.PI/2*h[r];var c={top:-1,bottom:1,right:1,left:-1};o.labelDirection=o.tickDirection=o.nameDirection=c[a],t.get("axisTick.inside")&&(o.tickDirection=-o.tickDirection),T(e.labelInside,t.get("axisLabel.inside"))&&(o.labelDirection=-o.labelDirection);var d=e.rotate;return null==d&&(d=t.get("axisLabel.rotate")),o.labelRotation="top"===a?-d:d,o.z2=1,o}function Qg(t,e,i,n,o){var r=t.axis;if(!r.scale.isBlank()&&r.containData(e))if(t.involveSeries){var s=tm(e,t),l=s.payloadBatch,u=s.snapToValue;l[0]&&null==o.seriesIndex&&a(o,l[0]),!n&&t.snap&&r.containData(u)&&null!=u&&(e=u),i.showPointer(t,e,l,o),i.showTooltip(t,s,u)}else i.showPointer(t,e)}function tm(t,e){var i=e.axis,n=i.dim,o=t,a=[],r=Number.MAX_VALUE,s=-1;return _P(e.seriesModels,function(e,l){var u,h,c=e.getData().mapDimension(n,!0);if(e.getAxisTooltipData){var d=e.getAxisTooltipData(c,t,i);h=d.dataIndices,u=d.nestestValue}else{if(!(h=e.getData().indicesOfNearest(c[0],t,"category"===i.type?.5:null)).length)return;u=e.getData().get(c[0],h[0])}if(null!=u&&isFinite(u)){var f=t-u,p=Math.abs(f);p<=r&&((p=0&&s<0)&&(r=p,s=f,o=u,a.length=0),_P(h,function(t){a.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})}))}}),{payloadBatch:a,snapToValue:o}}function em(t,e,i,n){t[e.key]={value:i,payloadBatch:n}}function im(t,e,i,n){var o=i.payloadBatch,a=e.axis,r=a.model,s=e.axisPointerModel;if(e.triggerTooltip&&o.length){var l=e.coordSys.model,u=Ah(l),h=t.map[u];h||(h=t.map[u]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(h)),h.dataByAxis.push({axisDim:a.dim,axisIndex:r.componentIndex,axisType:r.type,axisId:r.id,value:n,valueLabelOpt:{precision:s.get("label.precision"),formatter:s.get("label.formatter")},seriesDataIndices:o.slice()})}}function nm(t,e,i){var n=i.axesInfo=[];_P(e,function(e,i){var o=e.axisPointerModel.option,a=t[i];a?(!e.useHandle&&(o.status="show"),o.value=a.value,o.seriesDataIndices=(a.payloadBatch||[]).slice()):!e.useHandle&&(o.status="hide"),"show"===o.status&&n.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:o.value})})}function om(t,e,i,n){if(!lm(e)&&t.list.length){var o=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};n({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:i.tooltipOption,position:i.position,dataIndexInside:o.dataIndexInside,dataIndex:o.dataIndex,seriesIndex:o.seriesIndex,dataByCoordSys:t.list})}else n({type:"hideTip"})}function am(t,e,i){var n=i.getZr(),o=bP(n).axisPointerLastHighlights||{},a=bP(n).axisPointerLastHighlights={};_P(t,function(t,e){var i=t.axisPointerModel.option;"show"===i.status&&_P(i.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;a[e]=t})});var r=[],s=[];d(o,function(t,e){!a[e]&&s.push(t)}),d(a,function(t,e){!o[e]&&r.push(t)}),s.length&&i.dispatchAction({type:"downplay",escapeConnect:!0,batch:s}),r.length&&i.dispatchAction({type:"highlight",escapeConnect:!0,batch:r})}function rm(t,e){for(var i=0;i<(t||[]).length;i++){var n=t[i];if(e.axis.dim===n.axisDim&&e.axis.model.componentIndex===n.axisIndex)return n}}function sm(t){var e=t.axis.model,i={},n=i.axisDim=t.axis.dim;return i.axisIndex=i[n+"AxisIndex"]=e.componentIndex,i.axisName=i[n+"AxisName"]=e.name,i.axisId=i[n+"AxisId"]=e.id,i}function lm(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function um(t,e,i){if(!U_.node){var n=e.getZr();SP(n).records||(SP(n).records={}),hm(n,e),(SP(n).records[t]||(SP(n).records[t]={})).handler=i}}function hm(t,e){function i(i,n){t.on(i,function(i){var o=pm(e);MP(SP(t).records,function(t){t&&n(t,i,o.dispatchAction)}),cm(o.pendings,e)})}SP(t).initialized||(SP(t).initialized=!0,i("click",v(fm,"click")),i("mousemove",v(fm,"mousemove")),i("globalout",dm))}function cm(t,e){var i,n=t.showTip.length,o=t.hideTip.length;n?i=t.showTip[n-1]:o&&(i=t.hideTip[o-1]),i&&(i.dispatchAction=null,e.dispatchAction(i))}function dm(t,e,i){t.handler("leave",null,i)}function fm(t,e,i,n){e.handler(t,i,n)}function pm(t){var e={showTip:[],hideTip:[]},i=function(n){var o=e[n.type];o?o.push(n):(n.dispatchAction=i,t.dispatchAction(n))};return{dispatchAction:i,pendings:e}}function gm(t,e){if(!U_.node){var i=e.getZr();(SP(i).records||{})[t]&&(SP(i).records[t]=null)}}function mm(){}function vm(t,e,i,n){ym(TP(i).lastProp,n)||(TP(i).lastProp=n,e?Io(i,n,t):(i.stopAnimation(),i.attr(n)))}function ym(t,e){if(w(t)&&w(e)){var i=!0;return d(e,function(e,n){i=i&&ym(t[n],e)}),!!i}return t===e}function xm(t,e){t[e.get("label.show")?"show":"hide"]()}function _m(t){return{position:t.position.slice(),rotation:t.rotation||0}}function wm(t,e,i){var n=e.get("z"),o=e.get("zlevel");t&&t.traverse(function(t){"group"!==t.type&&(null!=n&&(t.z=n),null!=o&&(t.zlevel=o),t.silent=i)})}function bm(t){var e,i=t.get("type"),n=t.getModel(i+"Style");return"line"===i?(e=n.getLineStyle()).fill=null:"shadow"===i&&((e=n.getAreaStyle()).stroke=null),e}function Sm(t,e,i,n,o){var a=Im(i.get("value"),e.axis,e.ecModel,i.get("seriesDataIndices"),{precision:i.get("label.precision"),formatter:i.get("label.formatter")}),r=i.getModel("label"),s=qM(r.get("padding")||0),l=r.getFont(),u=ke(a,l),h=o.position,c=u.width+s[1]+s[3],d=u.height+s[0]+s[2],f=o.align;"right"===f&&(h[0]-=c),"center"===f&&(h[0]-=c/2);var p=o.verticalAlign;"bottom"===p&&(h[1]-=d),"middle"===p&&(h[1]-=d/2),Mm(h,c,d,n);var g=r.get("backgroundColor");g&&"auto"!==g||(g=e.get("axisLine.lineStyle.color")),t.label={shape:{x:0,y:0,width:c,height:d,r:r.get("borderRadius")},position:h.slice(),style:{text:a,textFont:l,textFill:r.getTextColor(),textPosition:"inside",fill:g,stroke:r.get("borderColor")||"transparent",lineWidth:r.get("borderWidth")||0,shadowBlur:r.get("shadowBlur"),shadowColor:r.get("shadowColor"),shadowOffsetX:r.get("shadowOffsetX"),shadowOffsetY:r.get("shadowOffsetY")},z2:10}}function Mm(t,e,i,n){var o=n.getWidth(),a=n.getHeight();t[0]=Math.min(t[0]+e,o)-e,t[1]=Math.min(t[1]+i,a)-i,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}function Im(t,e,i,n,o){t=e.scale.parse(t);var a=e.scale.getLabel(t,{precision:o.precision}),r=o.formatter;if(r){var s={value:Xl(e,t),seriesData:[]};d(n,function(t){var e=i.getSeriesByIndex(t.seriesIndex),n=t.dataIndexInside,o=e&&e.getDataParams(n);o&&s.seriesData.push(o)}),_(r)?a=r.replace("{value}",a):x(r)&&(a=r(s))}return a}function Tm(t,e,i){var n=xt();return Mt(n,n,i.rotation),St(n,n,i.position),Do([t.dataToCoord(e),(i.labelOffset||0)+(i.labelDirection||1)*(i.labelMargin||0)],n)}function Am(t,e,i,n,o,a){var r=FD.innerTextLayout(i.rotation,0,i.labelDirection);i.labelMargin=o.get("label.margin"),Sm(e,n,o,a,{position:Tm(n.axis,t,i),align:r.textAlign,verticalAlign:r.textVerticalAlign})}function Dm(t,e,i){return i=i||0,{x1:t[i],y1:t[1-i],x2:e[i],y2:e[1-i]}}function Cm(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}function Lm(t,e,i,n,o,a){return{cx:t,cy:e,r0:i,r:n,startAngle:o,endAngle:a,clockwise:!0}}function km(t,e){var i={};return i[e.dim+"AxisIndex"]=e.index,t.getCartesian(i)}function Pm(t){return"x"===t.dim?0:1}function Nm(t){return t.isHorizontal()?0:1}function Om(t,e){var i=t.getRect();return[i[kP[e]],i[kP[e]]+i[PP[e]]]}function Em(t,e,i){var n=new yM({shape:{x:t.x-10,y:t.y-10,width:0,height:t.height+20}});return To(n,{shape:{width:t.width+20,height:t.height+20}},e,i),n}function Rm(t,e,i){if(t.count())for(var n,o=e.coordinateSystem,a=e.getLayerSeries(),r=t.mapDimension("single"),s=t.mapDimension("value"),l=f(a,function(e){return f(e.indices,function(e){var i=o.dataToPoint(t.get(r,e));return i[1]=t.get(s,e),i})}),u=zm(l),h=u.y0,c=i/u.max,d=a.length,p=a[0].indices.length,g=0;ga&&(a=u),n.push(u)}for(var h=0;ha&&(a=d)}return r.y0=o,r.max=a,r}function Bm(t){var e=0;d(t.children,function(t){Bm(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function Vm(t,e,i){function n(){r.ignore=r.hoverIgnore}function o(){r.ignore=r.normalIgnore}tb.call(this);var a=new hM({z2:zP});a.seriesIndex=e.seriesIndex;var r=new rM({z2:BP,silent:t.getModel("label").get("silent")});this.add(a),this.add(r),this.updateData(!0,t,"normal",e,i),this.on("emphasis",n).on("normal",o).on("mouseover",n).on("mouseout",o)}function Gm(t,e,i){var n=t.getVisual("color"),o=t.getVisual("visualMeta");o&&0!==o.length||(n=null);var a=t.getModel("itemStyle").get("color");if(a)return a;if(n)return n;if(0===t.depth)return i.option.color[0];var r=i.option.color.length;return a=i.option.color[Fm(t)%r]}function Fm(t){for(var e=t;e.depth>1;)e=e.parentNode;return l(t.getAncestors()[0].children,e)}function Wm(t,e,i){return i!==RP.NONE&&(i===RP.SELF?t===e:i===RP.ANCESTOR?t===e||t.isAncestorOf(e):t===e||t.isDescendantOf(e))}function Hm(t,e,i){e.getData().setItemVisual(t.dataIndex,"color",i)}function Zm(t,e){var i=t.children||[];t.children=Um(i,e),i.length&&d(t.children,function(t){Zm(t,e)})}function Um(t,e){if("function"==typeof e)return t.sort(e);var i="asc"===e;return t.sort(function(t,e){var n=(t.getValue()-e.getValue())*(i?1:-1);return 0===n?(t.dataIndex-e.dataIndex)*(i?-1:1):n})}function Xm(t,e){return e=e||[0,0],f(["x","y"],function(i,n){var o=this.getAxis(i),a=e[n],r=t[n]/2;return"category"===o.type?o.getBandWidth():Math.abs(o.dataToCoord(a-r)-o.dataToCoord(a+r))},this)}function jm(t,e){return e=e||[0,0],f([0,1],function(i){var n=e[i],o=t[i]/2,a=[],r=[];return a[i]=n-o,r[i]=n+o,a[1-i]=r[1-i]=e[1-i],Math.abs(this.dataToPoint(a)[i]-this.dataToPoint(r)[i])},this)}function Ym(t,e){var i=this.getAxis(),n=e instanceof Array?e[0]:e,o=(t instanceof Array?t[0]:t)/2;return"category"===i.type?i.getBandWidth():Math.abs(i.dataToCoord(n-o)-i.dataToCoord(n+o))}function qm(t,e){return f(["Radius","Angle"],function(i,n){var o=this["get"+i+"Axis"](),a=e[n],r=t[n]/2,s="dataTo"+i,l="category"===o.type?o.getBandWidth():Math.abs(o[s](a-r)-o[s](a+r));return"Angle"===i&&(l=l*Math.PI/180),l},this)}function Km(t){var e,i=t.type;if("path"===i){var n=t.shape,o=null!=n.width&&null!=n.height?{x:n.x||0,y:n.y||0,width:n.width,height:n.height}:null,a=lv(n);(e=Xn(a,null,o,n.layout||"center")).__customPathData=a}else"image"===i?(e=new fi({})).__customImagePath=t.style.image:"text"===i?(e=new rM({})).__customText=t.style.text:e=new(0,zM[i.charAt(0).toUpperCase()+i.slice(1)]);return e.__customGraphicType=i,e.name=t.name,e}function $m(t,e,n,o,a,r,s){var l={},u=n.style||{};if(n.shape&&(l.shape=i(n.shape)),n.position&&(l.position=n.position.slice()),n.scale&&(l.scale=n.scale.slice()),n.origin&&(l.origin=n.origin.slice()),n.rotation&&(l.rotation=n.rotation),"image"===t.type&&n.style){h=l.style={};d(["x","y","width","height"],function(e){Jm(e,h,u,t.style,r)})}if("text"===t.type&&n.style){var h=l.style={};d(["x","y"],function(e){Jm(e,h,u,t.style,r)}),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke)}if("group"!==t.type&&(t.useStyle(u),r)){t.style.opacity=0;var c=u.opacity;null==c&&(c=1),To(t,{style:{opacity:c}},o,e)}r?t.attr(l):Io(t,l,o,e),n.hasOwnProperty("z2")&&t.attr("z2",n.z2||0),n.hasOwnProperty("silent")&&t.attr("silent",n.silent),n.hasOwnProperty("invisible")&&t.attr("invisible",n.invisible),n.hasOwnProperty("ignore")&&t.attr("ignore",n.ignore),n.hasOwnProperty("info")&&t.attr("info",n.info);var f=n.styleEmphasis,p=!1===f;t.__cusHasEmphStl&&null==f||!t.__cusHasEmphStl&&p||(ro(t,f),t.__cusHasEmphStl=!p),s&&po(t,!p)}function Jm(t,e,i,n,o){null==i[t]||o||(e[t]=i[t],i[t]=n[t])}function Qm(t,e,i,n){function o(t){null==t&&(t=h),v&&(c=e.getItemModel(t),d=c.getModel(UP),f=c.getModel(XP),p=e.getItemVisual(t,"color"),v=!1)}var s=t.get("renderItem"),l=t.coordinateSystem,u={};l&&(u=l.prepareCustoms?l.prepareCustoms():YP[l.type](l));var h,c,d,f,p,g=r({getWidth:n.getWidth,getHeight:n.getHeight,getZr:n.getZr,getDevicePixelRatio:n.getDevicePixelRatio,value:function(t,i){return null==i&&(i=h),e.get(e.getDimension(t||0),i)},style:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(HP).getItemStyle();null!=p&&(r.fill=p);var s=e.getItemVisual(n,"opacity");return null!=s&&(r.opacity=s),mo(r,d,null,{autoColor:p,isRectText:!0}),r.text=d.getShallow("show")?A(t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},styleEmphasis:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(ZP).getItemStyle();return mo(r,f,null,{isRectText:!0},!0),r.text=f.getShallow("show")?D(t.getFormattedLabel(n,"emphasis"),t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},visual:function(t,i){return null==i&&(i=h),e.getItemVisual(i,t)},barLayout:function(t){if(l.getBaseAxis)return Ll(r({axis:l.getBaseAxis()},t),n)},currentSeriesIndices:function(){return i.getCurrentSeriesIndices()},font:function(t){return So(t,i)}},u.api||{}),m={context:{},seriesId:t.id,seriesName:t.name,seriesIndex:t.seriesIndex,coordSys:u.coordSys,dataInsideLength:e.count(),encode:tv(t.getData())},v=!0;return function(t,i){return h=t,v=!0,s&&s(r({dataIndexInside:t,dataIndex:e.getRawIndex(t),actionType:i?i.type:null},m),g)}}function tv(t){var e={};return d(t.dimensions,function(i,n){var o=t.getDimensionInfo(i);if(!o.isExtraCoord){var a=o.coordDim;(e[a]=e[a]||[])[o.coordDimIndex]=n}}),e}function ev(t,e,i,n,o,a){return(t=iv(t,e,i,n,o,a,!0))&&a.setItemGraphicEl(e,t),t}function iv(t,e,i,n,o,a,r){var s=!i,l=(i=i||{}).type,u=i.shape,h=i.style;if(t&&(s||null!=l&&l!==t.__customGraphicType||"path"===l&&uv(u)&&lv(u)!==t.__customPathData||"image"===l&&hv(h,"image")&&h.image!==t.__customImagePath||"text"===l&&hv(u,"text")&&h.text!==t.__customText)&&(o.remove(t),t=null),!s){var c=!t;return!t&&(t=Km(i)),$m(t,e,i,n,a,c,r),"group"===l&&nv(t,e,i,n,a),o.add(t),t}}function nv(t,e,i,n,o){var a=i.children,r=a?a.length:0,s=i.$mergeChildren,l="byName"===s||i.diffChildrenByName,u=!1===s;if(r||l||u)if(l)ov({oldChildren:t.children()||[],newChildren:a||[],dataIndex:e,animatableModel:n,group:t,data:o});else{u&&t.removeAll();for(var h=0;hn?t-=l+a:t+=a),null!=r&&(e+u+r>o?e-=u+r:e+=r),[t,e]}function Ov(t,e,i,n,o){var a=i.getOuterSize(),r=a.width,s=a.height;return t=Math.min(t+r,n)-r,e=Math.min(e+s,o)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}function Ev(t,e,i){var n=i[0],o=i[1],a=0,r=0,s=e.width,l=e.height;switch(t){case"inside":a=e.x+s/2-n/2,r=e.y+l/2-o/2;break;case"top":a=e.x+s/2-n/2,r=e.y-o-5;break;case"bottom":a=e.x+s/2-n/2,r=e.y+l+5;break;case"left":a=e.x-n-5,r=e.y+l/2-o/2;break;case"right":a=e.x+s+5,r=e.y+l/2-o/2}return[a,r]}function Rv(t){return"center"===t||"middle"===t}function zv(t){return t.get("stack")||"__ec_stack_"+t.seriesIndex}function Bv(t){return t.dim}function Vv(t,e){var i={};d(t,function(t,e){var n=t.getData(),o=t.coordinateSystem.getBaseAxis(),a=o.getExtent(),r="category"===o.type?o.getBandWidth():Math.abs(a[1]-a[0])/n.count(),s=i[Bv(o)]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},l=s.stacks;i[Bv(o)]=s;var u=zv(t);l[u]||s.autoWidthCount++,l[u]=l[u]||{width:0,maxWidth:0};var h=Vo(t.get("barWidth"),r),c=Vo(t.get("barMaxWidth"),r),d=t.get("barGap"),f=t.get("barCategoryGap");h&&!l[u].width&&(h=Math.min(s.remainedWidth,h),l[u].width=h,s.remainedWidth-=h),c&&(l[u].maxWidth=c),null!=d&&(s.gap=d),null!=f&&(s.categoryGap=f)});var n={};return d(i,function(t,e){n[e]={};var i=t.stacks,o=t.bandWidth,a=Vo(t.categoryGap,o),r=Vo(t.gap,1),s=t.remainedWidth,l=t.autoWidthCount,u=(s-a)/(l+(l-1)*r);u=Math.max(u,0),d(i,function(t,e){var i=t.maxWidth;i&&ie[0]&&(e=e.slice().reverse());var n=t.coordToPoint([e[0],i]),o=t.coordToPoint([e[1],i]);return{x1:n[0],y1:n[1],x2:o[0],y2:o[1]}}function jv(t){return t.getRadiusAxis().inverse?0:1}function Yv(t){var e=t[0],i=t[t.length-1];e&&i&&Math.abs(Math.abs(e.coord-i.coord)-360)<1e-4&&t.pop()}function qv(t,e,i){return{position:[t.cx,t.cy],rotation:i/180*Math.PI,labelDirection:-1,tickDirection:-1,nameDirection:1,labelRotate:e.getModel("axisLabel").get("rotate"),z2:1}}function Kv(t,e,i,n,o){var a=e.axis,r=a.dataToCoord(t),s=n.getAngleAxis().getExtent()[0];s=s/180*Math.PI;var l,u,h,c=n.getRadiusAxis().getExtent();if("radius"===a.dim){var d=xt();Mt(d,d,s),St(d,d,[n.cx,n.cy]),l=Do([r,-o],d);var f=e.getModel("axisLabel").get("rotate")||0,p=FD.innerTextLayout(s,f*Math.PI/180,-1);u=p.textAlign,h=p.textVerticalAlign}else{var g=c[1];l=n.coordToPoint([g+o,r]);var m=n.cx,v=n.cy;u=Math.abs(l[0]-m)/g<.3?"center":l[0]>m?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}function $v(t,e){e.update="updateView",Es(e,function(e,i){var n={};return i.eachComponent({mainType:"geo",query:e},function(i){i[t](e.name),d(i.coordinateSystem.regions,function(t){n[t.name]=i.isSelected(t.name)||!1})}),{selected:n,name:e.name}})}function Jv(t){var e={};d(t,function(t){e[t]=1}),t.length=0,d(e,function(e,i){t.push(i)})}function Qv(t){if(t)for(var e in t)if(t.hasOwnProperty(e))return!0}function ty(t,e,n){function o(){var t=function(){};return t.prototype.__hidden=t.prototype,new t}var a={};return MN(e,function(e){var r=a[e]=o();MN(t[e],function(t,o){if(hL.isValidType(o)){var a={type:o,visual:t};n&&n(a,e),r[o]=new hL(a),"opacity"===o&&((a=i(a)).type="colorAlpha",r.__hidden.__alphaForOpacity=new hL(a))}})}),a}function ey(t,e,n){var o;d(n,function(t){e.hasOwnProperty(t)&&Qv(e[t])&&(o=!0)}),o&&d(n,function(n){e.hasOwnProperty(n)&&Qv(e[n])?t[n]=i(e[n]):delete t[n]})}function iy(t,e,i,n,o,a){function r(t){return i.getItemVisual(h,t)}function s(t,e){i.setItemVisual(h,t,e)}function l(t,l){h=null==a?t:l;var c=i.getRawDataItem(h);if(!c||!1!==c.visualMap)for(var d=n.call(o,t),f=e[d],p=u[d],g=0,m=p.length;g1)return!1;var h=uy(i-t,o-t,n-e,a-e)/l;return!(h<0||h>1)}function ly(t){return t<=1e-6&&t>=-1e-6}function uy(t,e,i,n){return t*n-e*i}function hy(t,e,i){var n=this._targetInfoList=[],o={},a=dy(e,t);TN(PN,function(t,e){(!i||!i.include||AN(i.include,e)>=0)&&t(a,n,o)})}function cy(t){return t[0]>t[1]&&t.reverse(),t}function dy(t,e){return Vi(t,e,{includeMainTypes:LN})}function fy(t,e,i,n){var o=i.getAxis(["x","y"][t]),a=cy(f([0,1],function(t){return e?o.coordToData(o.toLocalCoord(n[t])):o.toGlobalCoord(o.dataToCoord(n[t]))})),r=[];return r[t]=a,r[1-t]=[NaN,NaN],{values:a,xyMinMax:r}}function py(t,e,i,n){return[e[0]-n[t]*i[0],e[1]-n[t]*i[1]]}function gy(t,e){var i=my(t),n=my(e),o=[i[0]/n[0],i[1]/n[1]];return isNaN(o[0])&&(o[0]=1),isNaN(o[1])&&(o[1]=1),o}function my(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}function vy(t,e,i,n,o){if(o){var a=t.getZr();a[VN]||(a[BN]||(a[BN]=yy),Nr(a,BN,i,e)(t,n))}}function yy(t,e){if(!t.isDisposed()){var i=t.getZr();i[VN]=!0,t.dispatchAction({type:"brushSelect",batch:e}),i[VN]=!1}}function xy(t,e,i,n){for(var o=0,a=e.length;o=0}function Ny(t,e,i){function n(t,e){return l(e.nodes,t)>=0}function o(t,n){var o=!1;return e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]&&(o=!0)})}),o}function a(t,n){n.nodes.push(t),e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]=!0})})}return function(i){var r={nodes:[],records:{}};if(e(function(t){r.records[t.name]={}}),!i)return r;a(i,r);var s;do{s=!1,t(function(t){!n(t,r)&&o(t,r)&&(a(t,r),s=!0)})}while(s);return r}}function Oy(t,e,i){var n=[1/0,-1/0];return $N(i,function(t){var i=t.getData();i&&$N(i.mapDimension(e,!0),function(t){var e=i.getApproximateExtent(t);e[0]n[1]&&(n[1]=e[1])})}),n[1]0?0:NaN);var r=i.getMax(!0);return null!=r&&"dataMax"!==r&&"function"!=typeof r?e[1]=r:o&&(e[1]=a>0?a-1:NaN),i.get("scale",!0)||(e[0]>0&&(e[0]=0),e[1]<0&&(e[1]=0)),e}function Ry(t,e){var i=t.getAxisModel(),n=t._percentWindow,o=t._valueWindow;if(n){var a=Zo(o,[0,500]);a=Math.min(a,20);var r=e||0===n[0]&&100===n[1];i.setRange(r?null:+o[0].toFixed(a),r?null:+o[1].toFixed(a))}}function zy(t){var e=t._minMaxSpan={},i=t._dataZoomModel;$N(["min","max"],function(n){e[n+"Span"]=i.get(n+"Span");var o=i.get(n+"ValueSpan");if(null!=o&&(e[n+"ValueSpan"]=o,null!=(o=t.getAxisModel().axis.scale.parse(o)))){var a=t._dataExtent;e[n+"Span"]=Bo(a[0]+o,a,[0,100],!0)}})}function By(t){var e={};return tO(["start","end","startValue","endValue","throttle"],function(i){t.hasOwnProperty(i)&&(e[i]=t[i])}),e}function Vy(t,e){var i=t._rangePropMode,n=t.get("rangeMode");tO([["start","startValue"],["end","endValue"]],function(t,o){var a=null!=e[t[0]],r=null!=e[t[1]];a&&!r?i[o]="percent":!a&&r?i[o]="value":n?i[o]=n[o]:a&&(i[o]="percent")})}function Gy(t){return{x:"y",y:"x",radius:"angle",angle:"radius"}[t]}function Fy(t){return"vertical"===t?"ns-resize":"ew-resize"}function Wy(t,e){var i=Uy(t),n=e.dataZoomId,o=e.coordId;d(i,function(t,i){var a=t.dataZoomInfos;a[n]&&l(e.allCoordIds,o)<0&&(delete a[n],t.count--)}),jy(i);var a=i[o];a||((a=i[o]={coordId:o,dataZoomInfos:{},count:0}).controller=Xy(t,a),a.dispatchAction=v(Yy,t)),!a.dataZoomInfos[n]&&a.count++,a.dataZoomInfos[n]=e;var r=qy(a.dataZoomInfos);a.controller.enable(r.controlType,r.opt),a.controller.setPointerChecker(e.containsPoint),Nr(a,"dispatchAction",e.dataZoomModel.get("throttle",!0),"fixRate")}function Hy(t,e){var i=Uy(t);d(i,function(t){t.controller.dispose();var i=t.dataZoomInfos;i[e]&&(delete i[e],t.count--)}),jy(i)}function Zy(t){return t.type+"\0_"+t.id}function Uy(t){var e=t.getZr();return e[fO]||(e[fO]={})}function Xy(t,e){var i=new oc(t.getZr());return d(["pan","zoom","scrollMove"],function(t){i.on(t,function(i){var n=[];d(e.dataZoomInfos,function(o){if(i.isAvailableBehavior(o.dataZoomModel.option)){var a=(o.getRange||{})[t],r=a&&a(e.controller,i);!o.dataZoomModel.get("disabled",!0)&&r&&n.push({dataZoomId:o.dataZoomId,start:r[0],end:r[1]})}}),n.length&&e.dispatchAction(n)})}),i}function jy(t){d(t,function(e,i){e.count||(e.controller.dispose(),delete t[i])})}function Yy(t,e){t.dispatchAction({type:"dataZoom",batch:e})}function qy(t){var e,i={type_true:2,type_move:1,type_false:0,type_undefined:-1},n=!0;return d(t,function(t){var o=t.dataZoomModel,a=!o.get("disabled",!0)&&(!o.get("zoomLock",!0)||"move");i["type_"+a]>i["type_"+e]&&(e=a),n&=o.get("preventDefaultMouseMove",!0)}),{controlType:e,opt:{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!0,preventDefaultMouseMove:!!n}}}function Ky(t){return function(e,i,n,o){var a=this._range,r=a.slice(),s=e.axisModels[0];if(s){var l=t(r,s,e,i,n,o);return QL(l,r,[0,100],"all"),this._range=r,a[0]!==r[0]||a[1]!==r[1]?r:void 0}}}function $y(t,e){return t&&t.hasOwnProperty&&t.hasOwnProperty(e)}function Jy(t,e,i,n){for(var o=e.targetVisuals[n],a=hL.prepareVisualTypes(o),r={color:t.getData().getVisual("color")},s=0,l=a.length;s=0&&(r[a]=+r[a].toFixed(h)),r}function fx(t,e){var n=t.getData(),o=t.coordinateSystem;if(e&&!cx(e)&&!y(e.coord)&&o){var a=o.dimensions,r=px(e,n,o,t);if((e=i(e)).type&&YO[e.type]&&r.baseAxis&&r.valueAxis){var s=XO(a,r.baseAxis.dim),l=XO(a,r.valueAxis.dim);e.coord=YO[e.type](n,r.baseDataDim,r.valueDataDim,s,l),e.value=e.coord[l]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)YO[u[h]]&&(u[h]=yx(n,n.mapDimension(a[h]),u[h]));e.coord=u}}return e}function px(t,e,i,n){var o={};return null!=t.valueIndex||null!=t.valueDim?(o.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,o.valueAxis=i.getAxis(gx(n,o.valueDataDim)),o.baseAxis=i.getOtherAxis(o.valueAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim)):(o.baseAxis=n.getBaseAxis(),o.valueAxis=i.getOtherAxis(o.baseAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim),o.valueDataDim=e.mapDimension(o.valueAxis.dim)),o}function gx(t,e){var i=t.getData(),n=i.dimensions;e=i.getDimension(e);for(var o=0;o=0)return!0}function Yx(t){for(var e=t.split(/\n+/g),i=[],n=f(Xx(e.shift()).split(pE),function(t){return{name:t,data:[]}}),o=0;o=0&&!i[o][n];o--);if(o<0){var a=t.queryComponents({mainType:"dataZoom",subType:"select",id:n})[0];if(a){var r=a.getPercentRange();i[0][n]={dataZoomId:n,start:r[0],end:r[1]}}}}),i.push(e)}function t_(t){var e=n_(t),i=e[e.length-1];e.length>1&&e.pop();var n={};return gE(i,function(t,i){for(var o=e.length-1;o>=0;o--)if(t=e[o][i]){n[i]=t;break}}),n}function e_(t){t[mE]=null}function i_(t){return n_(t).length}function n_(t){var e=t[mE];return e||(e=t[mE]=[{}]),e}function o_(t,e,i){(this._brushController=new zf(i.getZr())).on("brush",m(this._onBrush,this)).mount(),this._isZoomActive}function a_(t){var e={};return d(["xAxisIndex","yAxisIndex"],function(i){e[i]=t[i],null==e[i]&&(e[i]="all"),(!1===e[i]||"none"===e[i])&&(e[i]=[])}),e}function r_(t,e){t.setIconStatus("back",i_(e)>1?"emphasis":"normal")}function s_(t,e,i,n,o){var a=i._isZoomActive;n&&"takeGlobalCursor"===n.type&&(a="dataZoomSelect"===n.key&&n.dataZoomSelectActive),i._isZoomActive=a,t.setIconStatus("zoom",a?"emphasis":"normal");var r=new hy(a_(t.option),e,{include:["grid"]});i._brushController.setPanels(r.makePanelOpts(o,function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"})).enableBrush(!!a&&{brushType:"auto",brushStyle:{lineWidth:0,fill:"rgba(0,0,0,0.2)"}})}function l_(t){this.model=t}function u_(t){return SE(t)}function h_(){if(!TE&&AE){TE=!0;var t=AE.styleSheets;t.length<31?AE.createStyleSheet().addRule(".zrvml","behavior:url(#default#VML)"):t[0].addRule(".zrvml","behavior:url(#default#VML)")}}function c_(t){return parseInt(t,10)}function d_(t,e){h_(),this.root=t,this.storage=e;var i=document.createElement("div"),n=document.createElement("div");i.style.cssText="display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;",n.style.cssText="position:absolute;left:0;top:0;",t.appendChild(i),this._vmlRoot=n,this._vmlViewport=i,this.resize();var o=e.delFromStorage,a=e.addToStorage;e.delFromStorage=function(t){o.call(e,t),t&&t.onRemove&&t.onRemove(n)},e.addToStorage=function(t){t.onAdd&&t.onAdd(n),a.call(e,t)},this._firstPaint=!0}function f_(t){return function(){Yw('In IE8.0 VML mode painter not support method "'+t+'"')}}function p_(t){return document.createElementNS(sR,t)}function g_(t){return cR(1e4*t)/1e4}function m_(t){return t-vR}function v_(t,e){var i=e?t.textFill:t.fill;return null!=i&&i!==hR}function y_(t,e){var i=e?t.textStroke:t.stroke;return null!=i&&i!==hR}function x_(t,e){e&&__(t,"transform","matrix("+uR.call(e,",")+")")}function __(t,e,i){(!i||"linear"!==i.type&&"radial"!==i.type)&&t.setAttribute(e,i)}function w_(t,e,i){t.setAttributeNS("http://www.w3.org/1999/xlink",e,i)}function b_(t,e,i,n){if(v_(e,i)){var o=i?e.textFill:e.fill;o="transparent"===o?hR:o,"none"!==t.getAttribute("clip-path")&&o===hR&&(o="rgba(0, 0, 0, 0.002)"),__(t,"fill",o),__(t,"fill-opacity",null!=e.fillOpacity?e.fillOpacity*e.opacity:e.opacity)}else __(t,"fill",hR);if(y_(e,i)){var a=i?e.textStroke:e.stroke;__(t,"stroke",a="transparent"===a?hR:a),__(t,"stroke-width",(i?e.textStrokeWidth:e.lineWidth)/(!i&&e.strokeNoScale?n.getLineScale():1)),__(t,"paint-order",i?"stroke":"fill"),__(t,"stroke-opacity",null!=e.strokeOpacity?e.strokeOpacity:e.opacity),e.lineDash?(__(t,"stroke-dasharray",e.lineDash.join(",")),__(t,"stroke-dashoffset",cR(e.lineDashOffset||0))):__(t,"stroke-dasharray",""),e.lineCap&&__(t,"stroke-linecap",e.lineCap),e.lineJoin&&__(t,"stroke-linejoin",e.lineJoin),e.miterLimit&&__(t,"stroke-miterlimit",e.miterLimit)}else __(t,"stroke",hR)}function S_(t){for(var e=[],i=t.data,n=t.len(),o=0;o=gR||!m_(g)&&(d>-pR&&d<0||d>pR)==!!p;var y=g_(s+u*fR(c)),x=g_(l+h*dR(c));m&&(d=p?gR-1e-4:1e-4-gR,v=!0,9===o&&e.push("M",y,x));var _=g_(s+u*fR(c+d)),w=g_(l+h*dR(c+d));e.push("A",g_(u),g_(h),cR(f*mR),+v,+p,_,w);break;case lR.Z:a="Z";break;case lR.R:var _=g_(i[o++]),w=g_(i[o++]),b=g_(i[o++]),S=g_(i[o++]);e.push("M",_,w,"L",_+b,w,"L",_+b,w+S,"L",_,w+S,"L",_,w)}a&&e.push(a);for(var M=0;M=11),domSupported:"undefined"!=typeof document}}(navigator.userAgent),X_={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},j_={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},Y_=Object.prototype.toString,q_=Array.prototype,K_=q_.forEach,$_=q_.filter,J_=q_.slice,Q_=q_.map,tw=q_.reduce,ew={},iw=function(){return ew.createCanvas()};ew.createCanvas=function(){return document.createElement("canvas")};var nw,ow="__ec_primitive__";E.prototype={constructor:E,get:function(t){return this.data.hasOwnProperty(t)?this.data[t]:null},set:function(t,e){return this.data[t]=e},each:function(t,e){void 0!==e&&(t=m(t,e));for(var i in this.data)this.data.hasOwnProperty(i)&&t(this.data[i],i)},removeKey:function(t){delete this.data[t]}};var aw=(Object.freeze||Object)({$override:e,clone:i,merge:n,mergeAll:o,extend:a,defaults:r,createCanvas:iw,getContext:s,indexOf:l,inherits:u,mixin:h,isArrayLike:c,each:d,map:f,reduce:p,filter:g,find:function(t,e,i){if(t&&e)for(var n=0,o=t.length;n3&&(n=dw.call(n,1));for(var a=e.length,r=0;r4&&(n=dw.call(n,1,n.length-1));for(var a=n[n.length-1],r=e.length,s=0;s1&&n&&n.length>1){var a=ft(n)/ft(o);!isFinite(a)&&(a=1),e.pinchScale=a;var r=pt(n);return e.pinchX=r[0],e.pinchY=r[1],{type:"pinch",target:t[0].target,event:e}}}}},xw="silent";vt.prototype.dispose=function(){};var _w=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],ww=function(t,e,i,n){fw.call(this),this.storage=t,this.painter=e,this.painterRoot=n,i=i||new vt,this.proxy=null,this._hovered={},this._lastTouchMoment,this._lastX,this._lastY,this._gestureMgr,it.call(this),this.setHandlerProxy(i)};ww.prototype={constructor:ww,setHandlerProxy:function(t){this.proxy&&this.proxy.dispose(),t&&(d(_w,function(e){t.on&&t.on(e,this[e],this)},this),t.handler=this),this.proxy=t},mousemove:function(t){var e=t.zrX,i=t.zrY,n=this._hovered,o=n.target;o&&!o.__zr&&(o=(n=this.findHover(n.x,n.y)).target);var a=this._hovered=this.findHover(e,i),r=a.target,s=this.proxy;s.setCursor&&s.setCursor(r?r.cursor:"default"),o&&r!==o&&this.dispatchToElement(n,"mouseout",t),this.dispatchToElement(a,"mousemove",t),r&&r!==o&&this.dispatchToElement(a,"mouseover",t)},mouseout:function(t){this.dispatchToElement(this._hovered,"mouseout",t);var e,i=t.toElement||t.relatedTarget;do{i=i&&i.parentNode}while(i&&9!==i.nodeType&&!(e=i===this.painterRoot));!e&&this.trigger("globalout",{event:t})},resize:function(t){this._hovered={}},dispatch:function(t,e){var i=this[t];i&&i.call(this,e)},dispose:function(){this.proxy.dispose(),this.storage=this.proxy=this.painter=null},setCursorStyle:function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},dispatchToElement:function(t,e,i){var n=(t=t||{}).target;if(!n||!n.silent){for(var o="on"+e,a=gt(e,t,i);n&&(n[o]&&(a.cancelBubble=n[o].call(n,a)),n.trigger(e,a),n=n.parent,!a.cancelBubble););a.cancelBubble||(this.trigger(e,a),this.painter&&this.painter.eachOtherLayer(function(t){"function"==typeof t[o]&&t[o].call(t,a),t.trigger&&t.trigger(e,a)}))}},findHover:function(t,e,i){for(var n=this.storage.getDisplayList(),o={x:t,y:e},a=n.length-1;a>=0;a--){var r;if(n[a]!==i&&!n[a].ignore&&(r=yt(n[a],t,e))&&(!o.topTarget&&(o.topTarget=n[a]),r!==xw)){o.target=n[a];break}}return o},processGesture:function(t,e){this._gestureMgr||(this._gestureMgr=new vw);var i=this._gestureMgr;"start"===e&&i.clear();var n=i.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&i.clear(),n){var o=n.type;t.gestureEvent=o,this.dispatchToElement({target:n.target},o,n.event)}}},d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){ww.prototype[t]=function(e){var i=this.findHover(e.zrX,e.zrY),n=i.target;if("mousedown"===t)this._downEl=n,this._downPoint=[e.zrX,e.zrY],this._upEl=n;else if("mouseup"===t)this._upEl=n;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||uw(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(i,t,e)}}),h(ww,fw),h(ww,it);var bw="undefined"==typeof Float32Array?Array:Float32Array,Sw=(Object.freeze||Object)({create:xt,identity:_t,copy:wt,mul:bt,translate:St,rotate:Mt,scale:It,invert:Tt,clone:At}),Mw=_t,Iw=5e-5,Tw=function(t){(t=t||{}).position||(this.position=[0,0]),null==t.rotation&&(this.rotation=0),t.scale||(this.scale=[1,1]),this.origin=this.origin||null},Aw=Tw.prototype;Aw.transform=null,Aw.needLocalTransform=function(){return Dt(this.rotation)||Dt(this.position[0])||Dt(this.position[1])||Dt(this.scale[0]-1)||Dt(this.scale[1]-1)};var Dw=[];Aw.updateTransform=function(){var t=this.parent,e=t&&t.transform,i=this.needLocalTransform(),n=this.transform;if(i||e){n=n||xt(),i?this.getLocalTransform(n):Mw(n),e&&(i?bt(n,t.transform,n):wt(n,t.transform)),this.transform=n;var o=this.globalScaleRatio;if(null!=o&&1!==o){this.getGlobalScale(Dw);var a=Dw[0]<0?-1:1,r=Dw[1]<0?-1:1,s=((Dw[0]-a)*o+a)/Dw[0]||0,l=((Dw[1]-r)*o+r)/Dw[1]||0;n[0]*=s,n[1]*=s,n[2]*=l,n[3]*=l}this.invTransform=this.invTransform||xt(),Tt(this.invTransform,n)}else n&&Mw(n)},Aw.getLocalTransform=function(t){return Tw.getLocalTransform(this,t)},Aw.setTransform=function(t){var e=this.transform,i=t.dpr||1;e?t.setTransform(i*e[0],i*e[1],i*e[2],i*e[3],i*e[4],i*e[5]):t.setTransform(i,0,0,i,0,0)},Aw.restoreTransform=function(t){var e=t.dpr||1;t.setTransform(e,0,0,e,0,0)};var Cw=[],Lw=xt();Aw.setLocalTransform=function(t){if(t){var e=t[0]*t[0]+t[1]*t[1],i=t[2]*t[2]+t[3]*t[3],n=this.position,o=this.scale;Dt(e-1)&&(e=Math.sqrt(e)),Dt(i-1)&&(i=Math.sqrt(i)),t[0]<0&&(e=-e),t[3]<0&&(i=-i),n[0]=t[4],n[1]=t[5],o[0]=e,o[1]=i,this.rotation=Math.atan2(-t[1]/i,t[0]/e)}},Aw.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(bt(Cw,t.invTransform,e),e=Cw);var i=this.origin;i&&(i[0]||i[1])&&(Lw[4]=i[0],Lw[5]=i[1],bt(Cw,e,Lw),Cw[4]-=i[0],Cw[5]-=i[1],e=Cw),this.setLocalTransform(e)}},Aw.getGlobalScale=function(t){var e=this.transform;return t=t||[],e?(t[0]=Math.sqrt(e[0]*e[0]+e[1]*e[1]),t[1]=Math.sqrt(e[2]*e[2]+e[3]*e[3]),e[0]<0&&(t[0]=-t[0]),e[3]<0&&(t[1]=-t[1]),t):(t[0]=1,t[1]=1,t)},Aw.transformCoordToLocal=function(t,e){var i=[t,e],n=this.invTransform;return n&&Q(i,i,n),i},Aw.transformCoordToGlobal=function(t,e){var i=[t,e],n=this.transform;return n&&Q(i,i,n),i},Tw.getLocalTransform=function(t,e){Mw(e=e||[]);var i=t.origin,n=t.scale||[1,1],o=t.rotation||0,a=t.position||[0,0];return i&&(e[4]-=i[0],e[5]-=i[1]),It(e,e,n),o&&Mt(e,e,o),i&&(e[4]+=i[0],e[5]+=i[1]),e[4]+=a[0],e[5]+=a[1],e};var kw={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),(t*=2)<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-kw.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*kw.bounceIn(2*t):.5*kw.bounceOut(2*t-1)+.5}};Ct.prototype={constructor:Ct,step:function(t,e){if(this._initialized||(this._startTime=t+this._delay,this._initialized=!0),this._paused)this._pausedTime+=e;else{var i=(t-this._startTime-this._pausedTime)/this._life;if(!(i<0)){i=Math.min(i,1);var n=this.easing,o="string"==typeof n?kw[n]:n,a="function"==typeof o?o(i):i;return this.fire("frame",a),1===i?this.loop?(this.restart(t),"restart"):(this._needsRemove=!0,"destroy"):null}}},restart:function(t){var e=(t-this._startTime-this._pausedTime)%this._life;this._startTime=t-e+this.gap,this._pausedTime=0,this._needsRemove=!1},fire:function(t,e){this[t="on"+t]&&this[t](this._target,e)},pause:function(){this._paused=!0},resume:function(){this._paused=!1}};var Pw=function(){this.head=null,this.tail=null,this._len=0},Nw=Pw.prototype;Nw.insert=function(t){var e=new Ow(t);return this.insertEntry(e),e},Nw.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},Nw.remove=function(t){var e=t.prev,i=t.next;e?e.next=i:this.head=i,i?i.prev=e:this.tail=e,t.next=t.prev=null,this._len--},Nw.len=function(){return this._len},Nw.clear=function(){this.head=this.tail=null,this._len=0};var Ow=function(t){this.value=t,this.next,this.prev},Ew=function(t){this._list=new Pw,this._map={},this._maxSize=t||10,this._lastRemovedEntry=null},Rw=Ew.prototype;Rw.put=function(t,e){var i=this._list,n=this._map,o=null;if(null==n[t]){var a=i.len(),r=this._lastRemovedEntry;if(a>=this._maxSize&&a>0){var s=i.head;i.remove(s),delete n[s.key],o=s.value,this._lastRemovedEntry=s}r?r.value=e:r=new Ow(e),r.key=t,i.insertEntry(r),n[t]=r}return o},Rw.get=function(t){var e=this._map[t],i=this._list;if(null!=e)return e!==i.tail&&(i.remove(e),i.insertEntry(e)),e.value},Rw.clear=function(){this._list.clear(),this._map={}};var zw={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]},Bw=new Ew(20),Vw=null,Gw=Ut,Fw=Xt,Ww=(Object.freeze||Object)({parse:Gt,lift:Ht,toHex:Zt,fastLerp:Ut,fastMapToColor:Gw,lerp:Xt,mapToColor:Fw,modifyHSL:jt,modifyAlpha:Yt,stringify:qt}),Hw=Array.prototype.slice,Zw=function(t,e,i,n){this._tracks={},this._target=t,this._loop=e||!1,this._getter=i||Kt,this._setter=n||$t,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};Zw.prototype={when:function(t,e){var i=this._tracks;for(var n in e)if(e.hasOwnProperty(n)){if(!i[n]){i[n]=[];var o=this._getter(this._target,n);if(null==o)continue;0!==t&&i[n].push({time:0,value:ae(o)})}i[n].push({time:t,value:e[n]})}return this},during:function(t){return this._onframeList.push(t),this},pause:function(){for(var t=0;t=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height},clone:function(){return new de(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},de.create=function(t){return new de(t.x,t.y,t.width,t.height)};var tb=function(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};tb.prototype={constructor:tb,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,i=0;i=0&&(i.splice(n,0,t),this._doAdd(t))}return this},_doAdd:function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__storage,i=this.__zr;e&&e!==t.__storage&&(e.addToStorage(t),t instanceof tb&&t.addChildrenToStorage(e)),i&&i.refresh()},remove:function(t){var e=this.__zr,i=this.__storage,n=this._children,o=l(n,t);return o<0?this:(n.splice(o,1),t.parent=null,i&&(i.delFromStorage(t),t instanceof tb&&t.delChildrenFromStorage(i)),e&&e.refresh(),this)},removeAll:function(){var t,e,i=this._children,n=this.__storage;for(e=0;e=0&&(this.delFromStorage(t),this._roots.splice(o,1),t instanceof tb&&t.delChildrenFromStorage(this))}},addToStorage:function(t){return t&&(t.__storage=this,t.dirty(!1)),this},delFromStorage:function(t){return t&&(t.__storage=null),this},dispose:function(){this._renderList=this._roots=null},displayableSortFunc:we};var ob={shadowBlur:1,shadowOffsetX:1,shadowOffsetY:1,textShadowBlur:1,textShadowOffsetX:1,textShadowOffsetY:1,textBoxShadowBlur:1,textBoxShadowOffsetX:1,textBoxShadowOffsetY:1},ab=function(t,e,i){return ob.hasOwnProperty(e)?i*=t.dpr:i},rb={NONE:0,STYLE_BIND:1,PLAIN_TEXT:2},sb=9,lb=[["shadowBlur",0],["shadowOffsetX",0],["shadowOffsetY",0],["shadowColor","#000"],["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]],ub=function(t){this.extendFrom(t,!1)};ub.prototype={constructor:ub,fill:"#000",stroke:null,opacity:1,fillOpacity:null,strokeOpacity:null,lineDash:null,lineDashOffset:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,lineWidth:1,strokeNoScale:!1,text:null,font:null,textFont:null,fontStyle:null,fontWeight:null,fontSize:null,fontFamily:null,textTag:null,textFill:"#000",textStroke:null,textWidth:null,textHeight:null,textStrokeWidth:0,textLineHeight:null,textPosition:"inside",textRect:null,textOffset:null,textAlign:null,textVerticalAlign:null,textDistance:5,textShadowColor:"transparent",textShadowBlur:0,textShadowOffsetX:0,textShadowOffsetY:0,textBoxShadowColor:"transparent",textBoxShadowBlur:0,textBoxShadowOffsetX:0,textBoxShadowOffsetY:0,transformText:!1,textRotation:0,textOrigin:null,textBackgroundColor:null,textBorderColor:null,textBorderWidth:0,textBorderRadius:0,textPadding:null,rich:null,truncate:null,blend:null,bind:function(t,e,i){var n=this,o=i&&i.style,a=!o||t.__attrCachedBy!==rb.STYLE_BIND;t.__attrCachedBy=rb.STYLE_BIND;for(var r=0;r0},extendFrom:function(t,e){if(t)for(var i in t)!t.hasOwnProperty(i)||!0!==e&&(!1===e?this.hasOwnProperty(i):null==t[i])||(this[i]=t[i])},set:function(t,e){"string"==typeof t?this[t]=e:this.extendFrom(t,!0)},clone:function(){var t=new this.constructor;return t.extendFrom(this,!0),t},getGradient:function(t,e,i){for(var n=("radial"===e.type?Se:be)(t,e,i),o=e.colorStops,a=0;a=0&&i.splice(n,1),t.__hoverMir=null},clearHover:function(t){for(var e=this._hoverElements,i=0;i15)break}s.__drawIndex=m,s.__drawIndex0&&t>n[0]){for(r=0;rt);r++);a=i[n[r]]}if(n.splice(r+1,0,t),i[t]=e,!e.virtual)if(a){var l=a.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else Yw("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var i,n,o=this._zlevelList;for(n=0;n0?.01:0),this._needsManuallyCompositing),a.__builtin__||Yw("ZLevel "+s+" has been used by unkown layer "+a.id),a!==i&&(a.__used=!0,a.__startIndex!==o&&(a.__dirty=!0),a.__startIndex=o,a.incremental?a.__drawIndex=-1:a.__drawIndex=o,e(o),i=a),r.__dirty&&(a.__dirty=!0,a.incremental&&a.__drawIndex<0&&(a.__drawIndex=o))}e(o),this.eachBuiltinLayer(function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)})},clear:function(){return this.eachBuiltinLayer(this._clearLayer),this},_clearLayer:function(t){t.clear()},setBackgroundColor:function(t){this._backgroundColor=t},configLayer:function(t,e){if(e){var i=this._layerConfig;i[t]?n(i[t],e,!0):i[t]=e;for(var o=0;o=0&&this._clips.splice(e,1)},removeAnimator:function(t){for(var e=t.getClips(),i=0;i=0||n&&l(n,r)<0)){var s=e.getShallow(r);null!=s&&(o[t[a][0]]=s)}}return o}},tS=Qb([["lineWidth","width"],["stroke","color"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),eS={getLineStyle:function(t){var e=tS(this,t),i=this.getLineDash(e.lineWidth);return i&&(e.lineDash=i),e},getLineDash:function(t){null==t&&(t=1);var e=this.get("type"),i=Math.max(t,2),n=4*t;return"solid"===e||null==e?null:"dashed"===e?[n,n]:[i,i]}},iS=Qb([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),nS={getAreaStyle:function(t,e){return iS(this,t,e)}},oS=Math.pow,aS=Math.sqrt,rS=1e-8,sS=1e-4,lS=aS(3),uS=1/3,hS=V(),cS=V(),dS=V(),fS=Math.min,pS=Math.max,gS=Math.sin,mS=Math.cos,vS=2*Math.PI,yS=V(),xS=V(),_S=V(),wS=[],bS=[],SS={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},MS=[],IS=[],TS=[],AS=[],DS=Math.min,CS=Math.max,LS=Math.cos,kS=Math.sin,PS=Math.sqrt,NS=Math.abs,OS="undefined"!=typeof Float32Array,ES=function(t){this._saveData=!t,this._saveData&&(this.data=[]),this._ctx=null};ES.prototype={constructor:ES,_xi:0,_yi:0,_x0:0,_y0:0,_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,setScale:function(t,e){this._ux=NS(1/Xw/t)||0,this._uy=NS(1/Xw/e)||0},getContext:function(){return this._ctx},beginPath:function(t){return this._ctx=t,t&&t.beginPath(),t&&(this.dpr=t.dpr),this._saveData&&(this._len=0),this._lineDash&&(this._lineDash=null,this._dashOffset=0),this},moveTo:function(t,e){return this.addData(SS.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},lineTo:function(t,e){var i=NS(t-this._xi)>this._ux||NS(e-this._yi)>this._uy||this._len<5;return this.addData(SS.L,t,e),this._ctx&&i&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),i&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,i,n,o,a){return this.addData(SS.C,t,e,i,n,o,a),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,i,n,o,a):this._ctx.bezierCurveTo(t,e,i,n,o,a)),this._xi=o,this._yi=a,this},quadraticCurveTo:function(t,e,i,n){return this.addData(SS.Q,t,e,i,n),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,i,n):this._ctx.quadraticCurveTo(t,e,i,n)),this._xi=i,this._yi=n,this},arc:function(t,e,i,n,o,a){return this.addData(SS.A,t,e,i,i,n,o-n,0,a?0:1),this._ctx&&this._ctx.arc(t,e,i,n,o,a),this._xi=LS(o)*i+t,this._yi=kS(o)*i+e,this},arcTo:function(t,e,i,n,o){return this._ctx&&this._ctx.arcTo(t,e,i,n,o),this},rect:function(t,e,i,n){return this._ctx&&this._ctx.rect(t,e,i,n),this.addData(SS.R,t,e,i,n),this},closePath:function(){this.addData(SS.Z);var t=this._ctx,e=this._x0,i=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,i),t.closePath()),this._xi=e,this._yi=i,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t,this._dashIdx=0;for(var e=0,i=0;ie.length&&(this._expandData(),e=this.data);for(var i=0;i0&&f<=t||h<0&&f>=t||0===h&&(c>0&&p<=e||c<0&&p>=e);)f+=h*(i=r[n=this._dashIdx]),p+=c*i,this._dashIdx=(n+1)%g,h>0&&fl||c>0&&pu||s[n%2?"moveTo":"lineTo"](h>=0?DS(f,t):CS(f,t),c>=0?DS(p,e):CS(p,e));h=f-t,c=p-e,this._dashOffset=-PS(h*h+c*c)},_dashedBezierTo:function(t,e,i,n,o,a){var r,s,l,u,h,c=this._dashSum,d=this._dashOffset,f=this._lineDash,p=this._ctx,g=this._xi,m=this._yi,v=tn,y=0,x=this._dashIdx,_=f.length,w=0;for(d<0&&(d=c+d),d%=c,r=0;r<1;r+=.1)s=v(g,t,i,o,r+.1)-v(g,t,i,o,r),l=v(m,e,n,a,r+.1)-v(m,e,n,a,r),y+=PS(s*s+l*l);for(;x<_&&!((w+=f[x])>d);x++);for(r=(w-d)/y;r<=1;)u=v(g,t,i,o,r),h=v(m,e,n,a,r),x%2?p.moveTo(u,h):p.lineTo(u,h),r+=f[x]/y,x=(x+1)%_;x%2!=0&&p.lineTo(o,a),s=o-u,l=a-h,this._dashOffset=-PS(s*s+l*l)},_dashedQuadraticTo:function(t,e,i,n){var o=i,a=n;i=(i+2*t)/3,n=(n+2*e)/3,t=(this._xi+2*t)/3,e=(this._yi+2*e)/3,this._dashedBezierTo(t,e,i,n,o,a)},toStatic:function(){var t=this.data;t instanceof Array&&(t.length=this._len,OS&&(this.data=new Float32Array(t)))},getBoundingRect:function(){MS[0]=MS[1]=TS[0]=TS[1]=Number.MAX_VALUE,IS[0]=IS[1]=AS[0]=AS[1]=-Number.MAX_VALUE;for(var t=this.data,e=0,i=0,n=0,o=0,a=0;al||NS(r-o)>u||c===h-1)&&(t.lineTo(a,r),n=a,o=r);break;case SS.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=g>m?g:m,b=g>m?1:g/m,S=g>m?m/g:1,M=v+y;Math.abs(g-m)>.001?(t.translate(f,p),t.rotate(x),t.scale(b,S),t.arc(0,0,w,v,M,1-_),t.scale(1/b,1/S),t.rotate(-x),t.translate(-f,-p)):t.arc(f,p,w,v,M,1-_),1===c&&(e=LS(v)*g+f,i=kS(v)*m+p),n=LS(M)*g+f,o=kS(M)*m+p;break;case SS.R:e=n=s[c],i=o=s[c+1],t.rect(s[c++],s[c++],s[c++],s[c++]);break;case SS.Z:t.closePath(),n=e,o=i}}}},ES.CMD=SS;var RS=2*Math.PI,zS=2*Math.PI,BS=ES.CMD,VS=2*Math.PI,GS=1e-4,FS=[-1,-1,-1],WS=[-1,-1],HS=fb.prototype.getCanvasPattern,ZS=Math.abs,US=new ES(!0);Pn.prototype={constructor:Pn,type:"path",__dirtyPath:!0,strokeContainThreshold:5,subPixelOptimize:!1,brush:function(t,e){var i=this.style,n=this.path||US,o=i.hasStroke(),a=i.hasFill(),r=i.fill,s=i.stroke,l=a&&!!r.colorStops,u=o&&!!s.colorStops,h=a&&!!r.image,c=o&&!!s.image;if(i.bind(t,this,e),this.setTransform(t),this.__dirty){var d;l&&(d=d||this.getBoundingRect(),this._fillGradient=i.getGradient(t,r,d)),u&&(d=d||this.getBoundingRect(),this._strokeGradient=i.getGradient(t,s,d))}l?t.fillStyle=this._fillGradient:h&&(t.fillStyle=HS.call(r,t)),u?t.strokeStyle=this._strokeGradient:c&&(t.strokeStyle=HS.call(s,t));var f=i.lineDash,p=i.lineDashOffset,g=!!t.setLineDash,m=this.getGlobalScale();if(n.setScale(m[0],m[1]),this.__dirtyPath||f&&!g&&o?(n.beginPath(t),f&&!g&&(n.setLineDash(f),n.setLineDashOffset(p)),this.buildPath(n,this.shape,!1),this.path&&(this.__dirtyPath=!1)):(t.beginPath(),this.path.rebuildPath(t)),a)if(null!=i.fillOpacity){v=t.globalAlpha;t.globalAlpha=i.fillOpacity*i.opacity,n.fill(t),t.globalAlpha=v}else n.fill(t);if(f&&g&&(t.setLineDash(f),t.lineDashOffset=p),o)if(null!=i.strokeOpacity){var v=t.globalAlpha;t.globalAlpha=i.strokeOpacity*i.opacity,n.stroke(t),t.globalAlpha=v}else n.stroke(t);f&&g&&t.setLineDash([]),null!=i.text&&(this.restoreTransform(t),this.drawRectText(t,this.getBoundingRect()))},buildPath:function(t,e,i){},createPathProxy:function(){this.path=new ES},getBoundingRect:function(){var t=this._rect,e=this.style,i=!t;if(i){var n=this.path;n||(n=this.path=new ES),this.__dirtyPath&&(n.beginPath(),this.buildPath(n,this.shape,!1)),t=n.getBoundingRect()}if(this._rect=t,e.hasStroke()){var o=this._rectWithStroke||(this._rectWithStroke=t.clone());if(this.__dirty||i){o.copy(t);var a=e.lineWidth,r=e.strokeNoScale?this.getLineScale():1;e.hasFill()||(a=Math.max(a,this.strokeContainThreshold||4)),r>1e-10&&(o.width+=a/r,o.height+=a/r,o.x-=a/r/2,o.y-=a/r/2)}return o}return t},contain:function(t,e){var i=this.transformCoordToLocal(t,e),n=this.getBoundingRect(),o=this.style;if(t=i[0],e=i[1],n.contain(t,e)){var a=this.path.data;if(o.hasStroke()){var r=o.lineWidth,s=o.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(o.hasFill()||(r=Math.max(r,this.strokeContainThreshold)),kn(a,r/s,t,e)))return!0}if(o.hasFill())return Ln(a,t,e)}return!1},dirty:function(t){null==t&&(t=!0),t&&(this.__dirtyPath=t,this._rect=null),this.__dirty=this.__dirtyText=!0,this.__zr&&this.__zr.refresh(),this.__clipTarget&&this.__clipTarget.dirty()},animateShape:function(t){return this.animate("shape",t)},attrKV:function(t,e){"shape"===t?(this.setShape(e),this.__dirtyPath=!0,this._rect=null):di.prototype.attrKV.call(this,t,e)},setShape:function(t,e){var i=this.shape;if(i){if(w(t))for(var n in t)t.hasOwnProperty(n)&&(i[n]=t[n]);else i[t]=e;this.dirty(!0)}return this},getLineScale:function(){var t=this.transform;return t&&ZS(t[0]-1)>1e-10&&ZS(t[3]-1)>1e-10?Math.sqrt(ZS(t[0]*t[3]-t[2]*t[1])):1}},Pn.extend=function(t){var e=function(e){Pn.call(this,e),t.style&&this.style.extendFrom(t.style,!1);var i=t.shape;if(i){this.shape=this.shape||{};var n=this.shape;for(var o in i)!n.hasOwnProperty(o)&&i.hasOwnProperty(o)&&(n[o]=i[o])}t.init&&t.init.call(this,e)};u(e,Pn);for(var i in t)"style"!==i&&"shape"!==i&&(e.prototype[i]=t[i]);return e},u(Pn,di);var XS=ES.CMD,jS=[[],[],[]],YS=Math.sqrt,qS=Math.atan2,KS=function(t,e){var i,n,o,a,r,s,l=t.data,u=XS.M,h=XS.C,c=XS.L,d=XS.R,f=XS.A,p=XS.Q;for(o=0,a=0;o=11?function(){var e,i=this.__clipPaths,n=this.style;if(i)for(var o=0;oi-2?i-1:c+1],u=t[c>i-3?i-1:c+2]);var p=d*d,g=d*p;n.push([Bn(s[0],f[0],l[0],u[0],d,p,g),Bn(s[1],f[1],l[1],u[1],d,p,g)])}return n},fM=function(t,e,i,n){var o,a,r,s,l=[],u=[],h=[],c=[];if(n){r=[1/0,1/0],s=[-1/0,-1/0];for(var d=0,f=t.length;d=i&&a>=o)return{x:i,y:o,width:n-i,height:a-o}},createIcon:Po,Group:tb,Image:fi,Text:rM,Circle:sM,Sector:hM,Ring:cM,Polygon:pM,Polyline:gM,Rect:yM,Line:_M,BezierCurve:bM,Arc:SM,IncrementalDisplayable:Zn,CompoundPath:MM,LinearGradient:TM,RadialGradient:AM,BoundingRect:de}),BM=["textStyle","color"],VM={getTextColor:function(t){var e=this.ecModel;return this.getShallow("color")||(!t&&e?e.get(BM):null)},getFont:function(){return So({fontStyle:this.getShallow("fontStyle"),fontWeight:this.getShallow("fontWeight"),fontSize:this.getShallow("fontSize"),fontFamily:this.getShallow("fontFamily")},this.ecModel)},getTextRect:function(t){return ke(t,this.getFont(),this.getShallow("align"),this.getShallow("verticalAlign")||this.getShallow("baseline"),this.getShallow("padding"),this.getShallow("lineHeight"),this.getShallow("rich"),this.getShallow("truncateText"))}},GM=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"],["textPosition"],["textAlign"]]),FM={getItemStyle:function(t,e){var i=GM(this,t,e),n=this.getBorderLineDash();return n&&(i.lineDash=n),i},getBorderLineDash:function(){var t=this.get("borderType");return"solid"===t||null==t?null:"dashed"===t?[5,5]:[1,1]}},WM=h,HM=Bi();No.prototype={constructor:No,init:null,mergeOption:function(t){n(this.option,t,!0)},get:function(t,e){return null==t?this.option:Oo(this.option,this.parsePath(t),!e&&Eo(this,t))},getShallow:function(t,e){var i=this.option,n=null==i?i:i[t],o=!e&&Eo(this,t);return null==n&&o&&(n=o.getShallow(t)),n},getModel:function(t,e){var i,n=null==t?this.option:Oo(this.option,t=this.parsePath(t));return e=e||(i=Eo(this,t))&&i.getModel(t),new No(n,e,this.ecModel)},isEmpty:function(){return null==this.option},restoreData:function(){},clone:function(){return new(0,this.constructor)(i(this.option))},setReadOnly:function(t){},parsePath:function(t){return"string"==typeof t&&(t=t.split(".")),t},customizeGetParent:function(t){HM(this).getParent=t},isAnimationEnabled:function(){if(!U_.node){if(null!=this.option.animation)return!!this.option.animation;if(this.parentModel)return this.parentModel.isAnimationEnabled()}}},ji(No),Yi(No),WM(No,eS),WM(No,nS),WM(No,VM),WM(No,FM);var ZM=0,UM=1e-4,XM=9007199254740991,jM=/^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/,YM=(Object.freeze||Object)({linearMap:Bo,parsePercent:Vo,round:Go,asc:Fo,getPrecision:Wo,getPrecisionSafe:Ho,getPixelPrecision:Zo,getPercentWithPrecision:Uo,MAX_SAFE_INTEGER:XM,remRadian:Xo,isRadianAroundZero:jo,parseDate:Yo,quantity:qo,nice:$o,quantile:function(t,e){var i=(t.length-1)*e+1,n=Math.floor(i),o=+t[n-1],a=i-n;return a?o+a*(t[n]-o):o},reformIntervals:Jo,isNumeric:Qo}),qM=L,KM=/([&<>"'])/g,$M={"&":"&","<":"<",">":">",'"':""","'":"'"},JM=["a","b","c","d","e","f","g"],QM=function(t,e){return"{"+t+(null==e?"":e)+"}"},tI=ze,eI=(Object.freeze||Object)({addCommas:ta,toCamelCase:ea,normalizeCssArray:qM,encodeHTML:ia,formatTpl:na,formatTplSimple:oa,getTooltipMarker:aa,formatTime:sa,capitalFirst:la,truncateText:tI,getTextBoundingRect:function(t){return ke(t.text,t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich,t.truncate)},getTextRect:function(t,e,i,n,o,a,r,s){return ke(t,e,i,n,o,s,a,r)}}),iI=d,nI=["left","right","top","bottom","width","height"],oI=[["width","left","right"],["height","top","bottom"]],aI=ua,rI=(v(ua,"vertical"),v(ua,"horizontal"),{getBoxLayoutParams:function(){return{left:this.get("left"),top:this.get("top"),right:this.get("right"),bottom:this.get("bottom"),width:this.get("width"),height:this.get("height")}}}),sI=Bi(),lI=No.extend({type:"component",id:"",name:"",mainType:"",subType:"",componentIndex:0,defaultOption:null,ecModel:null,dependentModels:[],uid:null,layoutMode:null,$constructor:function(t,e,i,n){No.call(this,t,e,i,n),this.uid=Ro("ec_cpt_model")},init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i)},mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,o=i?ga(t):{};n(t,e.getTheme().get(this.mainType)),n(t,this.getDefaultOption()),i&&pa(t,o,i)},mergeOption:function(t,e){n(this.option,t,!0);var i=this.layoutMode;i&&pa(this.option,t,i)},optionUpdated:function(t,e){},getDefaultOption:function(){var t=sI(this);if(!t.defaultOption){for(var e=[],i=this.constructor;i;){var o=i.prototype.defaultOption;o&&e.push(o),i=i.superClass}for(var a={},r=e.length-1;r>=0;r--)a=n(a,e[r],!0);t.defaultOption=a}return t.defaultOption},getReferringComponents:function(t){return this.ecModel.queryComponents({mainType:t,index:this.get(t+"Index",!0),id:this.get(t+"Id",!0)})}});$i(lI,{registerWhenExtend:!0}),function(t){var e={};t.registerSubTypeDefaulter=function(t,i){t=Ui(t),e[t.main]=i},t.determineSubType=function(i,n){var o=n.type;if(!o){var a=Ui(i).main;t.hasSubTypes(i)&&e[a]&&(o=e[a](n))}return o}}(lI),function(t,e){function i(t){var i={},a=[];return d(t,function(r){var s=n(i,r),u=o(s.originalDeps=e(r),t);s.entryCount=u.length,0===s.entryCount&&a.push(r),d(u,function(t){l(s.predecessor,t)<0&&s.predecessor.push(t);var e=n(i,t);l(e.successor,t)<0&&e.successor.push(r)})}),{graph:i,noEntryList:a}}function n(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}function o(t,e){var i=[];return d(t,function(t){l(e,t)>=0&&i.push(t)}),i}t.topologicalTravel=function(t,e,n,o){function a(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}if(t.length){var r=i(e),s=r.graph,l=r.noEntryList,u={};for(d(t,function(t){u[t]=!0});l.length;){var h=l.pop(),c=s[h],f=!!u[h];f&&(n.call(o,h,c.originalDeps.slice()),delete u[h]),d(c.successor,f?function(t){u[t]=!0,a(t)}:a)}d(u,function(){throw new Error("Circle dependency may exists")})}}}(lI,function(t){var e=[];return d(lI.getClassesByMainType(t),function(t){e=e.concat(t.prototype.dependencies||[])}),e=f(e,function(t){return Ui(t).main}),"dataset"!==t&&l(e,"dataset")<=0&&e.unshift("dataset"),e}),h(lI,rI);var uI="";"undefined"!=typeof navigator&&(uI=navigator.platform||"");var hI={color:["#c23531","#2f4554","#61a0a8","#d48265","#91c7ae","#749f83","#ca8622","#bda29a","#6e7074","#546570","#c4ccd3"],gradientColor:["#f6efa6","#d88273","#bf444c"],textStyle:{fontFamily:uI.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,animation:"auto",animationDuration:1e3,animationDurationUpdate:300,animationEasing:"exponentialOut",animationEasingUpdate:"cubicOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},cI=Bi(),dI={clearColorPalette:function(){cI(this).colorIdx=0,cI(this).colorNameMap={}},getColorFromPalette:function(t,e,i){var n=cI(e=e||this),o=n.colorIdx||0,a=n.colorNameMap=n.colorNameMap||{};if(a.hasOwnProperty(t))return a[t];var r=Di(this.get("color",!0)),s=this.get("colorLayer",!0),l=null!=i&&s?va(s,i):r;if((l=l||r)&&l.length){var u=l[o];return t&&(a[t]=u),n.colorIdx=(o+1)%l.length,u}}},fI={cartesian2d:function(t,e,i,n){var o=t.getReferringComponents("xAxis")[0],a=t.getReferringComponents("yAxis")[0];e.coordSysDims=["x","y"],i.set("x",o),i.set("y",a),xa(o)&&(n.set("x",o),e.firstCategoryDimIndex=0),xa(a)&&(n.set("y",a),e.firstCategoryDimIndex=1)},singleAxis:function(t,e,i,n){var o=t.getReferringComponents("singleAxis")[0];e.coordSysDims=["single"],i.set("single",o),xa(o)&&(n.set("single",o),e.firstCategoryDimIndex=0)},polar:function(t,e,i,n){var o=t.getReferringComponents("polar")[0],a=o.findAxisModel("radiusAxis"),r=o.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],i.set("radius",a),i.set("angle",r),xa(a)&&(n.set("radius",a),e.firstCategoryDimIndex=0),xa(r)&&(n.set("angle",r),e.firstCategoryDimIndex=1)},geo:function(t,e,i,n){e.coordSysDims=["lng","lat"]},parallel:function(t,e,i,n){var o=t.ecModel,a=o.getComponent("parallel",t.get("parallelIndex")),r=e.coordSysDims=a.dimensions.slice();d(a.parallelAxisIndex,function(t,a){var s=o.getComponent("parallelAxis",t),l=r[a];i.set(l,s),xa(s)&&null==e.firstCategoryDimIndex&&(n.set(l,s),e.firstCategoryDimIndex=a)})}},pI="original",gI="arrayRows",mI="objectRows",vI="keyedColumns",yI="unknown",xI="typedArray",_I="column",wI="row";_a.seriesDataToSource=function(t){return new _a({data:t,sourceFormat:S(t)?xI:pI,fromDataset:!1})},Yi(_a);var bI=Bi(),SI="\0_ec_inner",MI=No.extend({init:function(t,e,i,n){i=i||{},this.option=null,this._theme=new No(i),this._optionManager=n},setOption:function(t,e){k(!(SI in t),"please use chart.getOption()"),this._optionManager.setOption(t,e),this.resetOption(null)},resetOption:function(t){var e=!1,i=this._optionManager;if(!t||"recreate"===t){var n=i.mountOption("recreate"===t);this.option&&"recreate"!==t?(this.restoreData(),this.mergeOption(n)):Ea.call(this,n),e=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var o=i.getTimelineOption(this);o&&(this.mergeOption(o),e=!0)}if(!t||"recreate"===t||"media"===t){var a=i.getMediaOption(this,this._api);a.length&&d(a,function(t){this.mergeOption(t,e=!0)},this)}return e},mergeOption:function(t){var e=this.option,o=this._componentsMap,r=[];Sa(this),d(t,function(t,o){null!=t&&(lI.hasClass(o)?o&&r.push(o):e[o]=null==e[o]?i(t):n(e[o],t,!0))}),lI.topologicalTravel(r,lI.getAllClassMainTypes(),function(i,n){var r=Di(t[i]),s=Pi(o.get(i),r);Ni(s),d(s,function(t,e){var n=t.option;w(n)&&(t.keyInfo.mainType=i,t.keyInfo.subType=za(i,n,t.exist))});var l=Ra(o,n);e[i]=[],o.set(i,[]),d(s,function(t,n){var r=t.exist,s=t.option;if(k(w(s)||r,"Empty component definition"),s){var u=lI.getClass(i,t.keyInfo.subType,!0);if(r&&r instanceof u)r.name=t.keyInfo.name,r.mergeOption(s,this),r.optionUpdated(s,!1);else{var h=a({dependentModels:l,componentIndex:n},t.keyInfo);a(r=new u(s,this,this,h),h),r.init(s,this,this,h),r.optionUpdated(null,!0)}}else r.mergeOption({},this),r.optionUpdated({},!1);o.get(i)[n]=r,e[i][n]=r.option},this),"series"===i&&Ba(this,o.get("series"))},this),this._seriesIndicesMap=R(this._seriesIndices=this._seriesIndices||[])},getOption:function(){var t=i(this.option);return d(t,function(e,i){if(lI.hasClass(i)){for(var n=(e=Di(e)).length-1;n>=0;n--)Ei(e[n])&&e.splice(n,1);t[i]=e}}),delete t[SI],t},getTheme:function(){return this._theme},getComponent:function(t,e){var i=this._componentsMap.get(t);if(i)return i[e||0]},queryComponents:function(t){var e=t.mainType;if(!e)return[];var i=t.index,n=t.id,o=t.name,a=this._componentsMap.get(e);if(!a||!a.length)return[];var r;if(null!=i)y(i)||(i=[i]),r=g(f(i,function(t){return a[t]}),function(t){return!!t});else if(null!=n){var s=y(n);r=g(a,function(t){return s&&l(n,t.id)>=0||!s&&t.id===n})}else if(null!=o){var u=y(o);r=g(a,function(t){return u&&l(o,t.name)>=0||!u&&t.name===o})}else r=a.slice();return Va(r,t)},findComponents:function(t){var e=t.query,i=t.mainType,n=function(t){var e=i+"Index",n=i+"Id",o=i+"Name";return!t||null==t[e]&&null==t[n]&&null==t[o]?null:{mainType:i,index:t[e],id:t[n],name:t[o]}}(e);return function(e){return t.filter?g(e,t.filter):e}(Va(n?this.queryComponents(n):this._componentsMap.get(i),t))},eachComponent:function(t,e,i){var n=this._componentsMap;"function"==typeof t?(i=e,e=t,n.each(function(t,n){d(t,function(t,o){e.call(i,n,t,o)})})):_(t)?d(n.get(t),e,i):w(t)&&d(this.findComponents(t),e,i)},getSeriesByName:function(t){return g(this._componentsMap.get("series"),function(e){return e.name===t})},getSeriesByIndex:function(t){return this._componentsMap.get("series")[t]},getSeriesByType:function(t){return g(this._componentsMap.get("series"),function(e){return e.subType===t})},getSeries:function(){return this._componentsMap.get("series").slice()},getSeriesCount:function(){return this._componentsMap.get("series").length},eachSeries:function(t,e){d(this._seriesIndices,function(i){var n=this._componentsMap.get("series")[i];t.call(e,n,i)},this)},eachRawSeries:function(t,e){d(this._componentsMap.get("series"),t,e)},eachSeriesByType:function(t,e,i){d(this._seriesIndices,function(n){var o=this._componentsMap.get("series")[n];o.subType===t&&e.call(i,o,n)},this)},eachRawSeriesByType:function(t,e,i){return d(this.getSeriesByType(t),e,i)},isSeriesFiltered:function(t){return null==this._seriesIndicesMap.get(t.componentIndex)},getCurrentSeriesIndices:function(){return(this._seriesIndices||[]).slice()},filterSeries:function(t,e){Ba(this,g(this._componentsMap.get("series"),t,e))},restoreData:function(t){var e=this._componentsMap;Ba(this,e.get("series"));var i=[];e.each(function(t,e){i.push(e)}),lI.topologicalTravel(i,lI.getAllClassMainTypes(),function(i,n){d(e.get(i),function(e){("series"!==i||!Na(e,t))&&e.restoreData()})})}});h(MI,dI);var II=["getDom","getZr","getWidth","getHeight","getDevicePixelRatio","dispatchAction","isDisposed","on","off","getDataURL","getConnectedDataURL","getModel","getOption","getViewOfComponentModel","getViewOfSeriesModel"],TI={};Fa.prototype={constructor:Fa,create:function(t,e){var i=[];d(TI,function(n,o){var a=n.create(t,e);i=i.concat(a||[])}),this._coordinateSystems=i},update:function(t,e){d(this._coordinateSystems,function(i){i.update&&i.update(t,e)})},getCoordinateSystems:function(){return this._coordinateSystems.slice()}},Fa.register=function(t,e){TI[t]=e},Fa.get=function(t){return TI[t]};var AI=d,DI=i,CI=f,LI=n,kI=/^(min|max)?(.+)$/;Wa.prototype={constructor:Wa,setOption:function(t,e){t&&d(Di(t.series),function(t){t&&t.data&&S(t.data)&&N(t.data)}),t=DI(t,!0);var i=this._optionBackup,n=Ha.call(this,t,e,!i);this._newBaseOption=n.baseOption,i?(ja(i.baseOption,n.baseOption),n.timelineOptions.length&&(i.timelineOptions=n.timelineOptions),n.mediaList.length&&(i.mediaList=n.mediaList),n.mediaDefault&&(i.mediaDefault=n.mediaDefault)):this._optionBackup=n},mountOption:function(t){var e=this._optionBackup;return this._timelineOptions=CI(e.timelineOptions,DI),this._mediaList=CI(e.mediaList,DI),this._mediaDefault=DI(e.mediaDefault),this._currentMediaIndices=[],DI(t?e.baseOption:this._newBaseOption)},getTimelineOption:function(t){var e,i=this._timelineOptions;if(i.length){var n=t.getComponent("timeline");n&&(e=DI(i[n.getCurrentIndex()],!0))}return e},getMediaOption:function(t){var e=this._api.getWidth(),i=this._api.getHeight(),n=this._mediaList,o=this._mediaDefault,a=[],r=[];if(!n.length&&!o)return r;for(var s=0,l=n.length;s=1)&&(t=1),t}var i=this._upstream,n=t&&t.skip;if(this._dirty&&i){var o=this.context;o.data=o.outputData=i.context.outputData}this.__pipeline&&(this.__pipeline.currentTask=this);var a;this._plan&&!n&&(a=this._plan(this.context));var r=e(this._modBy),s=this._modDataCount||0,l=e(t&&t.modBy),u=t&&t.modDataCount||0;r===l&&s===u||(a="reset");var h;(this._dirty||"reset"===a)&&(this._dirty=!1,h=yr(this,n)),this._modBy=l,this._modDataCount=u;var c=t&&t.step;if(this._dueEnd=i?i._outputDueEnd:this._count?this._count(this.context):1/0,this._progress){var d=this._dueIndex,f=Math.min(null!=c?this._dueIndex+c:1/0,this._dueEnd);if(!n&&(h||d=i?null:t1&&a>0?e:t}};return s}();UI.dirty=function(){this._dirty=!0,this._onDirty&&this._onDirty(this.context)},UI.unfinished=function(){return this._progress&&this._dueIndex":"\n",s="richText"===n,l={},u=0,h=this.getData(),c=h.mapDimension("defaultedTooltip",!0),f=c.length,g=this.getRawValue(t),m=y(g),v=h.getItemVisual(t,"color");w(v)&&v.colorStops&&(v=(v.colorStops[0]||{}).color),v=v||"transparent";var x=(f>1||m&&!f?function(i){function o(t,i){var o=h.getDimensionInfo(i);if(o&&!1!==o.otherDims.tooltip){var c=o.type,d="sub"+a.seriesIndex+"at"+u,p=aa({color:v,type:"subItem",renderMode:n,markerId:d}),g="string"==typeof p?p:p.content,m=(r?g+ia(o.displayName||"-")+": ":"")+ia("ordinal"===c?t+"":"time"===c?e?"":sa("yyyy/MM/dd hh:mm:ss",t):ta(t));m&&f.push(m),s&&(l[d]=v,++u)}}var r=p(i,function(t,e,i){var n=h.getDimensionInfo(i);return t|=n&&!1!==n.tooltip&&null!=n.displayName},0),f=[];c.length?d(c,function(e){o(fr(h,t,e),e)}):d(i,o);var g=r?s?"\n":"
":"",m=g+f.join(g||", ");return{renderMode:n,content:m,style:l}}(g):o(f?fr(h,t,c[0]):m?g[0]:g)).content,_=a.seriesIndex+"at"+u,b=aa({color:v,type:"item",renderMode:n,markerId:_});l[_]=v,++u;var S=h.getName(t),M=this.name;Oi(this)||(M=""),M=M?ia(M)+(e?": ":r):"";var I="string"==typeof b?b:b.content;return{html:e?I+M+x:M+I+(S?ia(S)+": "+x:x),markers:l}},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,i){var n=this.ecModel,o=dI.getColorFromPalette.call(this,t,e,i);return o||(o=n.getColorFromPalette(t,e,i)),o},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});h(YI,ZI),h(YI,dI);var qI=function(){this.group=new tb,this.uid=Ro("viewComponent")};qI.prototype={constructor:qI,init:function(t,e){},render:function(t,e,i,n){},dispose:function(){},filterForExposedEvent:null};var KI=qI.prototype;KI.updateView=KI.updateLayout=KI.updateVisual=function(t,e,i,n){},ji(qI),$i(qI,{registerWhenExtend:!0});var $I=function(){var t=Bi();return function(e){var i=t(e),n=e.pipelineContext,o=i.large,a=i.progressiveRender,r=i.large=n.large,s=i.progressiveRender=n.progressiveRender;return!!(o^r||a^s)&&"reset"}},JI=Bi(),QI=$I();Ar.prototype={type:"chart",init:function(t,e){},render:function(t,e,i,n){},highlight:function(t,e,i,n){Cr(t.getData(),n,"emphasis")},downplay:function(t,e,i,n){Cr(t.getData(),n,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null,filterForExposedEvent:null};var tT=Ar.prototype;tT.updateView=tT.updateLayout=tT.updateVisual=function(t,e,i,n){this.render(t,e,i,n)},ji(Ar),$i(Ar,{registerWhenExtend:!0}),Ar.markUpdateMethod=function(t,e){JI(t).updateMethod=e};var eT={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},iT="\0__throttleOriginMethod",nT="\0__throttleRate",oT="\0__throttleType",aT={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var i=t.getData(),n=(t.visualColorAccessPath||"itemStyle.color").split("."),o=t.get(n)||t.getColorFromPalette(t.name,null,e.getSeriesCount());if(i.setVisual("color",o),!e.isSeriesFiltered(t)){"function"!=typeof o||o instanceof IM||i.each(function(e){i.setItemVisual(e,"color",o(t.getDataParams(e)))});return{dataEach:i.hasItemOption?function(t,e){var i=t.getItemModel(e).get(n,!0);null!=i&&t.setItemVisual(e,"color",i)}:null}}}},rT={toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}},sT=function(t,e){function i(t,e){if("string"!=typeof t)return t;var i=t;return d(e,function(t,e){i=i.replace(new RegExp("\\{\\s*"+e+"\\s*\\}","g"),t)}),i}function n(t){var e=a.get(t);if(null==e){for(var i=t.split("."),n=rT.aria,o=0;o1?"series.multiple.prefix":"series.single.prefix"),{seriesCount:r}),e.eachSeries(function(t,e){if(e1?"multiple":"single")+".";a=i(a=n(s?u+"withName":u+"withoutName"),{seriesId:t.seriesIndex,seriesName:t.get("name"),seriesType:o(t.subType)});var c=t.getData();window.data=c,c.count()>l?a+=i(n("data.partialData"),{displayCnt:l}):a+=n("data.allData");for(var d=[],p=0;pi.blockIndex?i.step:null,a=n&&n.modDataCount;return{step:o,modBy:null!=a?Math.ceil(a/o):null,modDataCount:a}}},uT.getPipeline=function(t){return this._pipelineMap.get(t)},uT.updateStreamModes=function(t,e){var i=this._pipelineMap.get(t.uid),n=t.getData().count(),o=i.progressiveEnabled&&e.incrementalPrepareRender&&n>=i.threshold,a=t.get("large")&&n>=t.get("largeThreshold"),r="mod"===t.get("progressiveChunkMode")?n:null;t.pipelineContext=i.context={progressiveRender:o,modDataCount:r,large:a}},uT.restorePipelines=function(t){var e=this,i=e._pipelineMap=R();t.eachSeries(function(t){var n=t.getProgressive(),o=t.uid;i.set(o,{id:o,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:n&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(n||700),count:0}),jr(e,t,t.dataTask)})},uT.prepareStageTasks=function(){var t=this._stageTaskMap,e=this.ecInstance.getModel(),i=this.api;d(this._allHandlers,function(n){var o=t.get(n.uid)||t.set(n.uid,[]);n.reset&&zr(this,n,o,e,i),n.overallReset&&Br(this,n,o,e,i)},this)},uT.prepareView=function(t,e,i,n){var o=t.renderTask,a=o.context;a.model=e,a.ecModel=i,a.api=n,o.__block=!t.incrementalPrepareRender,jr(this,e,o)},uT.performDataProcessorTasks=function(t,e){Rr(this,this._dataProcessorHandlers,t,e,{block:!0})},uT.performVisualTasks=function(t,e,i){Rr(this,this._visualHandlers,t,e,i)},uT.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},uT.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var hT=uT.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},cT=Ur(0);Er.wrapStageHandler=function(t,e){return x(t)&&(t={overallReset:t,seriesType:Yr(t)}),t.uid=Ro("stageHandler"),e&&(t.visualType=e),t};var dT,fT={},pT={};qr(fT,MI),qr(pT,Ga),fT.eachSeriesByType=fT.eachRawSeriesByType=function(t){dT=t},fT.eachComponent=function(t){"series"===t.mainType&&t.subType&&(dT=t.subType)};var gT=["#37A2DA","#32C5E9","#67E0E3","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#E062AE","#E690D1","#e7bcf3","#9d96f5","#8378EA","#96BFFF"],mT={color:gT,colorLayer:[["#37A2DA","#ffd85c","#fd7b5f"],["#37A2DA","#67E0E3","#FFDB5C","#ff9f7f","#E062AE","#9d96f5"],["#37A2DA","#32C5E9","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#e7bcf3","#8378EA","#96BFFF"],gT]},vT=["#dd6b66","#759aa0","#e69d87","#8dc1a9","#ea7e53","#eedd78","#73a373","#73b9bc","#7289ab","#91ca8c","#f49f42"],yT={color:vT,backgroundColor:"#333",tooltip:{axisPointer:{lineStyle:{color:"#eee"},crossStyle:{color:"#eee"}}},legend:{textStyle:{color:"#eee"}},textStyle:{color:"#eee"},title:{textStyle:{color:"#eee"}},toolbox:{iconStyle:{normal:{borderColor:"#eee"}}},dataZoom:{textStyle:{color:"#eee"}},visualMap:{textStyle:{color:"#eee"}},timeline:{lineStyle:{color:"#eee"},itemStyle:{normal:{color:vT[1]}},label:{normal:{textStyle:{color:"#eee"}}},controlStyle:{normal:{color:"#eee",borderColor:"#eee"}}},timeAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},logAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},valueAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},categoryAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},line:{symbol:"circle"},graph:{color:vT},gauge:{title:{textStyle:{color:"#eee"}}},candlestick:{itemStyle:{normal:{color:"#FD1050",color0:"#0CF49B",borderColor:"#FD1050",borderColor0:"#0CF49B"}}}};yT.categoryAxis.splitLine.show=!1,lI.extend({type:"dataset",defaultOption:{seriesLayoutBy:_I,sourceHeader:null,dimensions:null,source:null},optionUpdated:function(){wa(this)}}),qI.extend({type:"dataset"});var xT=Pn.extend({type:"ellipse",shape:{cx:0,cy:0,rx:0,ry:0},buildPath:function(t,e){var i=.5522848,n=e.cx,o=e.cy,a=e.rx,r=e.ry,s=a*i,l=r*i;t.moveTo(n-a,o),t.bezierCurveTo(n-a,o-l,n-s,o-r,n,o-r),t.bezierCurveTo(n+s,o-r,n+a,o-l,n+a,o),t.bezierCurveTo(n+a,o+l,n+s,o+r,n,o+r),t.bezierCurveTo(n-s,o+r,n-a,o+l,n-a,o),t.closePath()}}),_T=/[\s,]+/;$r.prototype.parse=function(t,e){e=e||{};var i=Kr(t);if(!i)throw new Error("Illegal svg");var n=new tb;this._root=n;var o=i.getAttribute("viewBox")||"",a=parseFloat(i.getAttribute("width")||e.width),r=parseFloat(i.getAttribute("height")||e.height);isNaN(a)&&(a=null),isNaN(r)&&(r=null),es(i,n,null,!0);for(var s=i.firstChild;s;)this._parseNode(s,n),s=s.nextSibling;var l,u;if(o){var h=P(o).split(_T);h.length>=4&&(l={x:parseFloat(h[0]||0),y:parseFloat(h[1]||0),width:parseFloat(h[2]),height:parseFloat(h[3])})}if(l&&null!=a&&null!=r&&(u=as(l,a,r),!e.ignoreViewBox)){var c=n;(n=new tb).add(c),c.scale=u.scale.slice(),c.position=u.position.slice()}return e.ignoreRootClip||null==a||null==r||n.setClipPath(new yM({shape:{x:0,y:0,width:a,height:r}})),{root:n,width:a,height:r,viewBoxRect:l,viewBoxTransform:u}},$r.prototype._parseNode=function(t,e){var i=t.nodeName.toLowerCase();"defs"===i?this._isDefine=!0:"text"===i&&(this._isText=!0);var n;if(this._isDefine){if(r=bT[i]){var o=r.call(this,t),a=t.getAttribute("id");a&&(this._defs[a]=o)}}else{var r=wT[i];r&&(n=r.call(this,t,e),e.add(n))}for(var s=t.firstChild;s;)1===s.nodeType&&this._parseNode(s,n),3===s.nodeType&&this._isText&&this._parseText(s,n),s=s.nextSibling;"defs"===i?this._isDefine=!1:"text"===i&&(this._isText=!1)},$r.prototype._parseText=function(t,e){if(1===t.nodeType){var i=t.getAttribute("dx")||0,n=t.getAttribute("dy")||0;this._textX+=parseFloat(i),this._textY+=parseFloat(n)}var o=new rM({style:{text:t.textContent,transformText:!0},position:[this._textX||0,this._textY||0]});Qr(e,o),es(t,o,this._defs);var a=o.style.fontSize;a&&a<9&&(o.style.fontSize=9,o.scale=o.scale||[1,1],o.scale[0]*=a/9,o.scale[1]*=a/9);var r=o.getBoundingRect();return this._textX+=r.width,e.add(o),o};var wT={g:function(t,e){var i=new tb;return Qr(e,i),es(t,i,this._defs),i},rect:function(t,e){var i=new yM;return Qr(e,i),es(t,i,this._defs),i.setShape({x:parseFloat(t.getAttribute("x")||0),y:parseFloat(t.getAttribute("y")||0),width:parseFloat(t.getAttribute("width")||0),height:parseFloat(t.getAttribute("height")||0)}),i},circle:function(t,e){var i=new sM;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),r:parseFloat(t.getAttribute("r")||0)}),i},line:function(t,e){var i=new _M;return Qr(e,i),es(t,i,this._defs),i.setShape({x1:parseFloat(t.getAttribute("x1")||0),y1:parseFloat(t.getAttribute("y1")||0),x2:parseFloat(t.getAttribute("x2")||0),y2:parseFloat(t.getAttribute("y2")||0)}),i},ellipse:function(t,e){var i=new xT;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),rx:parseFloat(t.getAttribute("rx")||0),ry:parseFloat(t.getAttribute("ry")||0)}),i},polygon:function(t,e){var i=t.getAttribute("points");i&&(i=ts(i));var n=new pM({shape:{points:i||[]}});return Qr(e,n),es(t,n,this._defs),n},polyline:function(t,e){var i=new Pn;Qr(e,i),es(t,i,this._defs);var n=t.getAttribute("points");return n&&(n=ts(n)),new gM({shape:{points:n||[]}})},image:function(t,e){var i=new fi;return Qr(e,i),es(t,i,this._defs),i.setStyle({image:t.getAttribute("xlink:href"),x:t.getAttribute("x"),y:t.getAttribute("y"),width:t.getAttribute("width"),height:t.getAttribute("height")}),i},text:function(t,e){var i=t.getAttribute("x")||0,n=t.getAttribute("y")||0,o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0;this._textX=parseFloat(i)+parseFloat(o),this._textY=parseFloat(n)+parseFloat(a);var r=new tb;return Qr(e,r),es(t,r,this._defs),r},tspan:function(t,e){var i=t.getAttribute("x"),n=t.getAttribute("y");null!=i&&(this._textX=parseFloat(i)),null!=n&&(this._textY=parseFloat(n));var o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0,r=new tb;return Qr(e,r),es(t,r,this._defs),this._textX+=o,this._textY+=a,r},path:function(t,e){var i=Rn(t.getAttribute("d")||"");return Qr(e,i),es(t,i,this._defs),i}},bT={lineargradient:function(t){var e=parseInt(t.getAttribute("x1")||0,10),i=parseInt(t.getAttribute("y1")||0,10),n=parseInt(t.getAttribute("x2")||10,10),o=parseInt(t.getAttribute("y2")||0,10),a=new TM(e,i,n,o);return Jr(t,a),a},radialgradient:function(t){}},ST={fill:"fill",stroke:"stroke","stroke-width":"lineWidth",opacity:"opacity","fill-opacity":"fillOpacity","stroke-opacity":"strokeOpacity","stroke-dasharray":"lineDash","stroke-dashoffset":"lineDashOffset","stroke-linecap":"lineCap","stroke-linejoin":"lineJoin","stroke-miterlimit":"miterLimit","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","text-align":"textAlign","alignment-baseline":"textBaseline"},MT=/url\(\s*#(.*?)\)/,IT=/(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g,TT=/([^\s:;]+)\s*:\s*([^:;]+)/g,AT=R(),DT={registerMap:function(t,e,i){var n;return y(e)?n=e:e.svg?n=[{type:"svg",source:e.svg,specialAreas:e.specialAreas}]:(e.geoJson&&!e.features&&(i=e.specialAreas,e=e.geoJson),n=[{type:"geoJSON",source:e,specialAreas:i}]),d(n,function(t){var e=t.type;"geoJson"===e&&(e=t.type="geoJSON"),(0,CT[e])(t)}),AT.set(t,n)},retrieveMap:function(t){return AT.get(t)}},CT={geoJSON:function(t){var e=t.source;t.geoJSON=_(e)?"undefined"!=typeof JSON&&JSON.parse?JSON.parse(e):new Function("return ("+e+");")():e},svg:function(t){t.svgXML=Kr(t.source)}},LT=k,kT=d,PT=x,NT=w,OT=lI.parseClassType,ET={zrender:"4.0.6"},RT=1e3,zT=1e3,BT=3e3,VT={PROCESSOR:{FILTER:RT,STATISTIC:5e3},VISUAL:{LAYOUT:zT,GLOBAL:2e3,CHART:BT,COMPONENT:4e3,BRUSH:5e3}},GT="__flagInMainProcess",FT="__optionUpdated",WT=/^[a-zA-Z0-9_]+$/;ls.prototype.on=ss("on"),ls.prototype.off=ss("off"),ls.prototype.one=ss("one"),h(ls,fw);var HT=us.prototype;HT._onframe=function(){if(!this._disposed){var t=this._scheduler;if(this[FT]){var e=this[FT].silent;this[GT]=!0,cs(this),ZT.update.call(this),this[GT]=!1,this[FT]=!1,gs.call(this,e),ms.call(this,e)}else if(t.unfinished){var i=1,n=this._model;this._api;t.unfinished=!1;do{var o=+new Date;t.performSeriesTasks(n),t.performDataProcessorTasks(n),fs(this,n),t.performVisualTasks(n),bs(this,this._model,0,"remain"),i-=+new Date-o}while(i>0&&t.unfinished);t.unfinished||this._zr.flush()}}},HT.getDom=function(){return this._dom},HT.getZr=function(){return this._zr},HT.setOption=function(t,e,i){var n;if(NT(e)&&(i=e.lazyUpdate,n=e.silent,e=e.notMerge),this[GT]=!0,!this._model||e){var o=new Wa(this._api),a=this._theme,r=this._model=new MI(null,null,a,o);r.scheduler=this._scheduler,r.init(null,null,a,o)}this._model.setOption(t,qT),i?(this[FT]={silent:n},this[GT]=!1):(cs(this),ZT.update.call(this),this._zr.flush(),this[FT]=!1,this[GT]=!1,gs.call(this,n),ms.call(this,n))},HT.setTheme=function(){console.error("ECharts#setTheme() is DEPRECATED in ECharts 3.0")},HT.getModel=function(){return this._model},HT.getOption=function(){return this._model&&this._model.getOption()},HT.getWidth=function(){return this._zr.getWidth()},HT.getHeight=function(){return this._zr.getHeight()},HT.getDevicePixelRatio=function(){return this._zr.painter.dpr||window.devicePixelRatio||1},HT.getRenderedCanvas=function(t){if(U_.canvasSupported)return(t=t||{}).pixelRatio=t.pixelRatio||1,t.backgroundColor=t.backgroundColor||this._model.get("backgroundColor"),this._zr.painter.getRenderedCanvas(t)},HT.getSvgDataUrl=function(){if(U_.svgSupported){var t=this._zr;return d(t.storage.getDisplayList(),function(t){t.stopAnimation(!0)}),t.painter.pathToDataUrl()}},HT.getDataURL=function(t){var e=(t=t||{}).excludeComponents,i=this._model,n=[],o=this;kT(e,function(t){i.eachComponent({mainType:t},function(t){var e=o._componentsMap[t.__viewId];e.group.ignore||(n.push(e),e.group.ignore=!0)})});var a="svg"===this._zr.painter.getType()?this.getSvgDataUrl():this.getRenderedCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return kT(n,function(t){t.group.ignore=!1}),a},HT.getConnectedDataURL=function(t){if(U_.canvasSupported){var e=this.group,n=Math.min,o=Math.max;if(eA[e]){var a=1/0,r=1/0,s=-1/0,l=-1/0,u=[],h=t&&t.pixelRatio||1;d(tA,function(h,c){if(h.group===e){var d=h.getRenderedCanvas(i(t)),f=h.getDom().getBoundingClientRect();a=n(f.left,a),r=n(f.top,r),s=o(f.right,s),l=o(f.bottom,l),u.push({dom:d,left:f.left,top:f.top})}});var c=(s*=h)-(a*=h),f=(l*=h)-(r*=h),p=iw();p.width=c,p.height=f;var g=Ii(p);return kT(u,function(t){var e=new fi({style:{x:t.left*h-a,y:t.top*h-r,image:t.dom}});g.add(e)}),g.refreshImmediately(),p.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}},HT.convertToPixel=v(hs,"convertToPixel"),HT.convertFromPixel=v(hs,"convertFromPixel"),HT.containPixel=function(t,e){var i;return t=Vi(this._model,t),d(t,function(t,n){n.indexOf("Models")>=0&&d(t,function(t){var o=t.coordinateSystem;if(o&&o.containPoint)i|=!!o.containPoint(e);else if("seriesModels"===n){var a=this._chartsMap[t.__viewId];a&&a.containPoint&&(i|=a.containPoint(e,t))}},this)},this),!!i},HT.getVisual=function(t,e){var i=(t=Vi(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),n=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?i.indexOfRawIndex(t.dataIndex):null;return null!=n?i.getItemVisual(n,e):i.getVisual(e)},HT.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},HT.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var ZT={prepareAndUpdate:function(t){cs(this),ZT.update.call(this,t)},update:function(t){var e=this._model,i=this._api,n=this._zr,o=this._coordSysMgr,a=this._scheduler;if(e){a.restoreData(e,t),a.performSeriesTasks(e),o.create(e,i),a.performDataProcessorTasks(e,t),fs(this,e),o.update(e,i),xs(e),a.performVisualTasks(e,t),_s(this,e,i,t);var r=e.get("backgroundColor")||"transparent";if(U_.canvasSupported)n.setBackgroundColor(r);else{var s=Gt(r);r=qt(s,"rgb"),0===s[3]&&(r="transparent")}Ss(e,i)}},updateTransform:function(t){var e=this._model,i=this,n=this._api;if(e){var o=[];e.eachComponent(function(a,r){var s=i.getViewOfComponentModel(r);if(s&&s.__alive)if(s.updateTransform){var l=s.updateTransform(r,e,n,t);l&&l.update&&o.push(s)}else o.push(s)});var a=R();e.eachSeries(function(o){var r=i._chartsMap[o.__viewId];if(r.updateTransform){var s=r.updateTransform(o,e,n,t);s&&s.update&&a.set(o.uid,1)}else a.set(o.uid,1)}),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0,dirtyMap:a}),bs(i,e,0,t,a),Ss(e,this._api)}},updateView:function(t){var e=this._model;e&&(Ar.markUpdateMethod(t,"updateView"),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0}),_s(this,this._model,this._api,t),Ss(e,this._api))},updateVisual:function(t){ZT.update.call(this,t)},updateLayout:function(t){ZT.update.call(this,t)}};HT.resize=function(t){this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var i=e.resetOption("media"),n=t&&t.silent;this[GT]=!0,i&&cs(this),ZT.update.call(this),this[GT]=!1,gs.call(this,n),ms.call(this,n)}},HT.showLoading=function(t,e){if(NT(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),QT[t]){var i=QT[t](this._api,e),n=this._zr;this._loadingFX=i,n.add(i)}},HT.hideLoading=function(){this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null},HT.makeActionFromEvent=function(t){var e=a({},t);return e.type=jT[t.type],e},HT.dispatchAction=function(t,e){NT(e)||(e={silent:!!e}),XT[t.type]&&this._model&&(this[GT]?this._pendingActions.push(t):(ps.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&U_.browser.weChat&&this._throttledZrFlush(),gs.call(this,e.silent),ms.call(this,e.silent)))},HT.appendData=function(t){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0},HT.on=ss("on"),HT.off=ss("off"),HT.one=ss("one");var UT=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];HT._initEvents=function(){kT(UT,function(t){var e=function(e){var i,n=this.getModel(),o=e.target;if("globalout"===t)i={};else if(o&&null!=o.dataIndex){var r=o.dataModel||n.getSeriesByIndex(o.seriesIndex);i=r&&r.getDataParams(o.dataIndex,o.dataType,o)||{}}else o&&o.eventData&&(i=a({},o.eventData));if(i){var s=i.componentType,l=i.componentIndex;"markLine"!==s&&"markPoint"!==s&&"markArea"!==s||(s="series",l=i.seriesIndex);var u=s&&null!=l&&n.getComponent(s,l),h=u&&this["series"===u.mainType?"_chartsMap":"_componentsMap"][u.__viewId];i.event=e,i.type=t,this._ecEventProcessor.eventInfo={targetEl:o,packedEvent:i,model:u,view:h},this.trigger(t,i)}};e.zrEventfulCallAtLast=!0,this._zr.on(t,e,this)},this),kT(jT,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},HT.isDisposed=function(){return this._disposed},HT.clear=function(){this.setOption({series:[]},!0)},HT.dispose=function(){if(!this._disposed){this._disposed=!0,Fi(this.getDom(),oA,"");var t=this._api,e=this._model;kT(this._componentsViews,function(i){i.dispose(e,t)}),kT(this._chartsViews,function(i){i.dispose(e,t)}),this._zr.dispose(),delete tA[this.id]}},h(us,fw),Ds.prototype={constructor:Ds,normalizeQuery:function(t){var e={},i={},n={};if(_(t)){var o=OT(t);e.mainType=o.main||null,e.subType=o.sub||null}else{var a=["Index","Name","Id"],r={name:1,dataIndex:1,dataType:1};d(t,function(t,o){for(var s=!1,l=0;l0&&h===o.length-u.length){var c=o.slice(0,h);"data"!==c&&(e.mainType=c,e[u.toLowerCase()]=t,s=!0)}}r.hasOwnProperty(o)&&(i[o]=t,s=!0),s||(n[o]=t)})}return{cptQuery:e,dataQuery:i,otherQuery:n}},filter:function(t,e,i){function n(t,e,i,n){return null==t[i]||e[n||i]===t[i]}var o=this.eventInfo;if(!o)return!0;var a=o.targetEl,r=o.packedEvent,s=o.model,l=o.view;if(!s||!l)return!0;var u=e.cptQuery,h=e.dataQuery;return n(u,s,"mainType")&&n(u,s,"subType")&&n(u,s,"index","componentIndex")&&n(u,s,"name")&&n(u,s,"id")&&n(h,r,"name")&&n(h,r,"dataIndex")&&n(h,r,"dataType")&&(!l.filterForExposedEvent||l.filterForExposedEvent(t,e.otherQuery,a,r))},afterTrigger:function(){this.eventInfo=null}};var XT={},jT={},YT=[],qT=[],KT=[],$T=[],JT={},QT={},tA={},eA={},iA=new Date-0,nA=new Date-0,oA="_echarts_instance_",aA=Ls;Bs(2e3,aT),Ns(BI),Os(5e3,function(t){var e=R();t.eachSeries(function(t){var i=t.get("stack");if(i){var n=e.get(i)||e.set(i,[]),o=t.getData(),a={stackResultDimension:o.getCalculationInfo("stackResultDimension"),stackedOverDimension:o.getCalculationInfo("stackedOverDimension"),stackedDimension:o.getCalculationInfo("stackedDimension"),stackedByDimension:o.getCalculationInfo("stackedByDimension"),isStackedByIndex:o.getCalculationInfo("isStackedByIndex"),data:o,seriesModel:t};if(!a.stackedDimension||!a.isStackedByIndex&&!a.stackedByDimension)return;n.length&&o.setCalculationInfo("stackedOnSeries",n[n.length-1].seriesModel),n.push(a)}}),e.each(ar)}),Gs("default",function(t,e){r(e=e||{},{text:"loading",color:"#c23531",textColor:"#000",maskColor:"rgba(255, 255, 255, 0.8)",zlevel:0});var i=new yM({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4}),n=new SM({shape:{startAngle:-lT/2,endAngle:-lT/2+.1,r:10},style:{stroke:e.color,lineCap:"round",lineWidth:5},zlevel:e.zlevel,z:10001}),o=new yM({style:{fill:"none",text:e.text,textPosition:"right",textDistance:10,textFill:e.textColor},zlevel:e.zlevel,z:10001});n.animateShape(!0).when(1e3,{endAngle:3*lT/2}).start("circularInOut"),n.animateShape(!0).when(1e3,{startAngle:3*lT/2}).delay(300).start("circularInOut");var a=new tb;return a.add(n),a.add(o),a.add(i),a.resize=function(){var e=t.getWidth()/2,a=t.getHeight()/2;n.setShape({cx:e,cy:a});var r=n.shape.r;o.setShape({x:e-r,y:a-r,width:2*r,height:2*r}),i.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},a.resize(),a}),Es({type:"highlight",event:"highlight",update:"highlight"},B),Es({type:"downplay",event:"downplay",update:"downplay"},B),Ps("light",mT),Ps("dark",yT);var rA={};Xs.prototype={constructor:Xs,add:function(t){return this._add=t,this},update:function(t){return this._update=t,this},remove:function(t){return this._remove=t,this},execute:function(){var t=this._old,e=this._new,i={},n=[],o=[];for(js(t,{},n,"_oldKeyGetter",this),js(e,i,o,"_newKeyGetter",this),a=0;ax[1]&&(x[1]=y)}e&&(this._nameList[d]=e[f])}this._rawCount=this._count=l,this._extent={},el(this)},yA._initDataFromProvider=function(t,e){if(!(t>=e)){for(var i,n=this._chunkSize,o=this._rawData,a=this._storage,r=this.dimensions,s=r.length,l=this._dimensionInfos,u=this._nameList,h=this._idList,c=this._rawExtent,d=this._nameRepeatCount={},f=this._chunkCount,p=0;pM[1]&&(M[1]=S)}if(!o.pure){var I=u[v];if(m&&null==I)if(null!=m.name)u[v]=I=m.name;else if(null!=i){var T=r[i],A=a[T][y];if(A){I=A[x];var D=l[T].ordinalMeta;D&&D.categories.length&&(I=D.categories[I])}}var C=null==m?null:m.id;null==C&&null!=I&&(d[I]=d[I]||0,C=I,d[I]>0&&(C+="__ec__"+d[I]),d[I]++),null!=C&&(h[v]=C)}}!o.persistent&&o.clean&&o.clean(),this._rawCount=this._count=e,this._extent={},el(this)}},yA.count=function(){return this._count},yA.getIndices=function(){var t=this._indices;if(t){var e=t.constructor,i=this._count;if(e===Array){n=new e(i);for(o=0;o=0&&e=0&&ea&&(a=s)}return i=[o,a],this._extent[t]=i,i},yA.getApproximateExtent=function(t){return t=this.getDimension(t),this._approximateExtent[t]||this.getDataExtent(t)},yA.setApproximateExtent=function(t,e){e=this.getDimension(e),this._approximateExtent[e]=t.slice()},yA.getCalculationInfo=function(t){return this._calculationInfo[t]},yA.setCalculationInfo=function(t,e){lA(t)?a(this._calculationInfo,t):this._calculationInfo[t]=e},yA.getSum=function(t){var e=0;if(this._storage[t])for(var i=0,n=this.count();i=this._rawCount||t<0)return-1;var e=this._indices,i=e[t];if(null!=i&&it))return a;o=a-1}}return-1},yA.indicesOfNearest=function(t,e,i){var n=[];if(!this._storage[t])return n;null==i&&(i=1/0);for(var o=Number.MAX_VALUE,a=-1,r=0,s=this.count();r=0&&a<0)&&(o=u,a=l,n.length=0),n.push(r))}return n},yA.getRawIndex=nl,yA.getRawDataItem=function(t){if(this._rawData.persistent)return this._rawData.getItem(this.getRawIndex(t));for(var e=[],i=0;i=l&&w<=u||isNaN(w))&&(a[r++]=c),c++;h=!0}else if(2===n){for(var d=this._storage[s],v=this._storage[e[1]],y=t[e[1]][0],x=t[e[1]][1],f=0;f=l&&w<=u||isNaN(w))&&(b>=y&&b<=x||isNaN(b))&&(a[r++]=c),c++}h=!0}}if(!h)if(1===n)for(m=0;m=l&&w<=u||isNaN(w))&&(a[r++]=M)}else for(m=0;mt[I][1])&&(S=!1)}S&&(a[r++]=this.getRawIndex(m))}return rb[1]&&(b[1]=w)}}}return o},yA.downSample=function(t,e,i,n){for(var o=sl(this,[t]),a=o._storage,r=[],s=Math.floor(1/e),l=a[t],u=this.count(),h=this._chunkSize,c=o._rawExtent[t],d=new($s(this))(u),f=0,p=0;pu-p&&(s=u-p,r.length=s);for(var g=0;gc[1]&&(c[1]=x),d[f++]=_}return o._count=f,o._indices=d,o.getRawIndex=ol,o},yA.getItemModel=function(t){var e=this.hostModel;return new No(this.getRawDataItem(t),e,e&&e.ecModel)},yA.diff=function(t){var e=this;return new Xs(t?t.getIndices():[],this.getIndices(),function(e){return al(t,e)},function(t){return al(e,t)})},yA.getVisual=function(t){var e=this._visual;return e&&e[t]},yA.setVisual=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setVisual(i,t[i]);else this._visual=this._visual||{},this._visual[t]=e},yA.setLayout=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setLayout(i,t[i]);else this._layout[t]=e},yA.getLayout=function(t){return this._layout[t]},yA.getItemLayout=function(t){return this._itemLayouts[t]},yA.setItemLayout=function(t,e,i){this._itemLayouts[t]=i?a(this._itemLayouts[t]||{},e):e},yA.clearItemLayouts=function(){this._itemLayouts.length=0},yA.getItemVisual=function(t,e,i){var n=this._itemVisuals[t],o=n&&n[e];return null!=o||i?o:this.getVisual(e)},yA.setItemVisual=function(t,e,i){var n=this._itemVisuals[t]||{},o=this.hasItemVisual;if(this._itemVisuals[t]=n,lA(e))for(var a in e)e.hasOwnProperty(a)&&(n[a]=e[a],o[a]=!0);else n[e]=i,o[e]=!0},yA.clearAllVisual=function(){this._visual={},this._itemVisuals=[],this.hasItemVisual={}};var xA=function(t){t.seriesIndex=this.seriesIndex,t.dataIndex=this.dataIndex,t.dataType=this.dataType};yA.setItemGraphicEl=function(t,e){var i=this.hostModel;e&&(e.dataIndex=t,e.dataType=this.dataType,e.seriesIndex=i&&i.seriesIndex,"group"===e.type&&e.traverse(xA,e)),this._graphicEls[t]=e},yA.getItemGraphicEl=function(t){return this._graphicEls[t]},yA.eachItemGraphicEl=function(t,e){d(this._graphicEls,function(i,n){i&&t&&t.call(e,i,n)})},yA.cloneShallow=function(t){if(!t){var e=f(this.dimensions,this.getDimensionInfo,this);t=new vA(e,this.hostModel)}if(t._storage=this._storage,Qs(t,this),this._indices){var i=this._indices.constructor;t._indices=new i(this._indices)}else t._indices=null;return t.getRawIndex=t._indices?ol:nl,t},yA.wrapMethod=function(t,e){var i=this[t];"function"==typeof i&&(this.__wrappedMethods=this.__wrappedMethods||[],this.__wrappedMethods.push(t),this[t]=function(){var t=i.apply(this,arguments);return e.apply(this,[t].concat(C(arguments)))})},yA.TRANSFERABLE_METHODS=["cloneShallow","downSample","map"],yA.CHANGABLE_METHODS=["filterSelf","selectRange"];var _A=function(t,e){return e=e||{},hl(e.coordDimensions||[],t,{dimsDef:e.dimensionsDefine||t.dimensionsDefine,encodeDef:e.encodeDefine||t.encodeDefine,dimCount:e.dimensionsCount,generateCoord:e.generateCoord,generateCoordCount:e.generateCoordCount})};xl.prototype.parse=function(t){return t},xl.prototype.getSetting=function(t){return this._setting[t]},xl.prototype.contain=function(t){var e=this._extent;return t>=e[0]&&t<=e[1]},xl.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},xl.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},xl.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1])},xl.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},xl.prototype.getExtent=function(){return this._extent.slice()},xl.prototype.setExtent=function(t,e){var i=this._extent;isNaN(t)||(i[0]=t),isNaN(e)||(i[1]=e)},xl.prototype.isBlank=function(){return this._isBlank},xl.prototype.setBlank=function(t){this._isBlank=t},xl.prototype.getLabel=null,ji(xl),$i(xl,{registerWhenExtend:!0}),_l.createByAxisModel=function(t){var e=t.option,i=e.data,n=i&&f(i,bl);return new _l({categories:n,needCollect:!n,deduplication:!1!==e.dedplication})};var wA=_l.prototype;wA.getOrdinal=function(t){return wl(this).get(t)},wA.parseAndCollect=function(t){var e,i=this._needCollect;if("string"!=typeof t&&!i)return t;if(i&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var n=wl(this);return null==(e=n.get(t))&&(i?(e=this.categories.length,this.categories[e]=t,n.set(t,e)):e=NaN),e};var bA=xl.prototype,SA=xl.extend({type:"ordinal",init:function(t,e){t&&!y(t)||(t=new _l({categories:t})),this._ordinalMeta=t,this._extent=e||[0,t.categories.length-1]},parse:function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},contain:function(t){return t=this.parse(t),bA.contain.call(this,t)&&null!=this._ordinalMeta.categories[t]},normalize:function(t){return bA.normalize.call(this,this.parse(t))},scale:function(t){return Math.round(bA.scale.call(this,t))},getTicks:function(){for(var t=[],e=this._extent,i=e[0];i<=e[1];)t.push(i),i++;return t},getLabel:function(t){if(!this.isBlank())return this._ordinalMeta.categories[t]},count:function(){return this._extent[1]-this._extent[0]+1},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},getOrdinalMeta:function(){return this._ordinalMeta},niceTicks:B,niceExtent:B});SA.create=function(){return new SA};var MA=Go,IA=Go,TA=xl.extend({type:"interval",_interval:0,_intervalPrecision:2,setExtent:function(t,e){var i=this._extent;isNaN(t)||(i[0]=parseFloat(t)),isNaN(e)||(i[1]=parseFloat(e))},unionExtent:function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),TA.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Ml(t)},getTicks:function(){return Al(this._interval,this._extent,this._niceExtent,this._intervalPrecision)},getLabel:function(t,e){if(null==t)return"";var i=e&&e.precision;return null==i?i=Ho(t)||0:"auto"===i&&(i=this._intervalPrecision),t=IA(t,i,!0),ta(t)},niceTicks:function(t,e,i){t=t||5;var n=this._extent,o=n[1]-n[0];if(isFinite(o)){o<0&&(o=-o,n.reverse());var a=Sl(n,t,e,i);this._intervalPrecision=a.intervalPrecision,this._interval=a.interval,this._niceExtent=a.niceTickExtent}},niceExtent:function(t){var e=this._extent;if(e[0]===e[1])if(0!==e[0]){var i=e[0];t.fixMax?e[0]-=i/2:(e[1]+=i/2,e[0]-=i/2)}else e[1]=1;var n=e[1]-e[0];isFinite(n)||(e[0]=0,e[1]=1),this.niceTicks(t.splitNumber,t.minInterval,t.maxInterval);var o=this._interval;t.fixMin||(e[0]=IA(Math.floor(e[0]/o)*o)),t.fixMax||(e[1]=IA(Math.ceil(e[1]/o)*o))}});TA.create=function(){return new TA};var AA="__ec_stack_",DA="undefined"!=typeof Float32Array?Float32Array:Array,CA={seriesType:"bar",plan:$I(),reset:function(t){if(Rl(t)&&zl(t)){var e=t.getData(),i=t.coordinateSystem,n=i.getBaseAxis(),o=i.getOtherAxis(n),a=e.mapDimension(o.dim),r=e.mapDimension(n.dim),s=o.isHorizontal(),l=s?0:1,u=Ol(Pl([t]),n,t).width;return u>.5||(u=.5),{progress:function(t,e){for(var n,h=new DA(2*t.count),c=[],d=[],f=0;null!=(n=t.next());)d[l]=e.get(a,n),d[1-l]=e.get(r,n),c=i.dataToPoint(d,null,c),h[f++]=c[0],h[f++]=c[1];e.setLayout({largePoints:h,barWidth:u,valueAxisStart:Bl(0,o),valueAxisHorizontal:s})}}}}},LA=TA.prototype,kA=Math.ceil,PA=Math.floor,NA=function(t,e,i,n){for(;i>>1;t[o][1]i&&(a=i);var r=EA.length,s=NA(EA,a,0,r),l=EA[Math.min(s,r-1)],u=l[1];"year"===l[0]&&(u*=$o(o/u/t,!0));var h=this.getSetting("useUTC")?0:60*new Date(+n[0]||+n[1]).getTimezoneOffset()*1e3,c=[Math.round(kA((n[0]-h)/u)*u+h),Math.round(PA((n[1]-h)/u)*u+h)];Tl(c,n),this._stepLvl=l,this._interval=u,this._niceExtent=c},parse:function(t){return+Yo(t)}});d(["contain","normalize"],function(t){OA.prototype[t]=function(e){return LA[t].call(this,this.parse(e))}});var EA=[["hh:mm:ss",1e3],["hh:mm:ss",5e3],["hh:mm:ss",1e4],["hh:mm:ss",15e3],["hh:mm:ss",3e4],["hh:mm\nMM-dd",6e4],["hh:mm\nMM-dd",3e5],["hh:mm\nMM-dd",6e5],["hh:mm\nMM-dd",9e5],["hh:mm\nMM-dd",18e5],["hh:mm\nMM-dd",36e5],["hh:mm\nMM-dd",72e5],["hh:mm\nMM-dd",216e5],["hh:mm\nMM-dd",432e5],["MM-dd\nyyyy",864e5],["MM-dd\nyyyy",1728e5],["MM-dd\nyyyy",2592e5],["MM-dd\nyyyy",3456e5],["MM-dd\nyyyy",432e6],["MM-dd\nyyyy",5184e5],["week",6048e5],["MM-dd\nyyyy",864e6],["week",12096e5],["week",18144e5],["month",26784e5],["week",36288e5],["month",53568e5],["week",6048e6],["quarter",8208e6],["month",107136e5],["month",13392e6],["half-year",16416e6],["month",214272e5],["month",26784e6],["year",32832e6]];OA.create=function(t){return new OA({useUTC:t.ecModel.get("useUTC")})};var RA=xl.prototype,zA=TA.prototype,BA=Ho,VA=Go,GA=Math.floor,FA=Math.ceil,WA=Math.pow,HA=Math.log,ZA=xl.extend({type:"log",base:10,$constructor:function(){xl.apply(this,arguments),this._originalScale=new TA},getTicks:function(){var t=this._originalScale,e=this._extent,i=t.getExtent();return f(zA.getTicks.call(this),function(n){var o=Go(WA(this.base,n));return o=n===e[0]&&t.__fixMin?Vl(o,i[0]):o,o=n===e[1]&&t.__fixMax?Vl(o,i[1]):o},this)},getLabel:zA.getLabel,scale:function(t){return t=RA.scale.call(this,t),WA(this.base,t)},setExtent:function(t,e){var i=this.base;t=HA(t)/HA(i),e=HA(e)/HA(i),zA.setExtent.call(this,t,e)},getExtent:function(){var t=this.base,e=RA.getExtent.call(this);e[0]=WA(t,e[0]),e[1]=WA(t,e[1]);var i=this._originalScale,n=i.getExtent();return i.__fixMin&&(e[0]=Vl(e[0],n[0])),i.__fixMax&&(e[1]=Vl(e[1],n[1])),e},unionExtent:function(t){this._originalScale.unionExtent(t);var e=this.base;t[0]=HA(t[0])/HA(e),t[1]=HA(t[1])/HA(e),RA.unionExtent.call(this,t)},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},niceTicks:function(t){t=t||10;var e=this._extent,i=e[1]-e[0];if(!(i===1/0||i<=0)){var n=qo(i);for(t/i*n<=.5&&(n*=10);!isNaN(n)&&Math.abs(n)<1&&Math.abs(n)>0;)n*=10;var o=[Go(FA(e[0]/n)*n),Go(GA(e[1]/n)*n)];this._interval=n,this._niceExtent=o}},niceExtent:function(t){zA.niceExtent.call(this,t);var e=this._originalScale;e.__fixMin=t.fixMin,e.__fixMax=t.fixMax}});d(["contain","normalize"],function(t){ZA.prototype[t]=function(e){return e=HA(e)/HA(this.base),RA[t].call(this,e)}}),ZA.create=function(){return new ZA};var UA={getMin:function(t){var e=this.option,i=t||null==e.rangeStart?e.min:e.rangeStart;return this.axis&&null!=i&&"dataMin"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getMax:function(t){var e=this.option,i=t||null==e.rangeEnd?e.max:e.rangeEnd;return this.axis&&null!=i&&"dataMax"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getNeedCrossZero:function(){var t=this.option;return null==t.rangeStart&&null==t.rangeEnd&&!t.scale},getCoordSysModel:B,setRange:function(t,e){this.option.rangeStart=t,this.option.rangeEnd=e},resetRange:function(){this.option.rangeStart=this.option.rangeEnd=null}},XA=Un({type:"triangle",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n+a),t.lineTo(i-o,n+a),t.closePath()}}),jA=Un({type:"diamond",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n),t.lineTo(i,n+a),t.lineTo(i-o,n),t.closePath()}}),YA=Un({type:"pin",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.x,n=e.y,o=e.width/5*3,a=Math.max(o,e.height),r=o/2,s=r*r/(a-r),l=n-a+r+s,u=Math.asin(s/r),h=Math.cos(u)*r,c=Math.sin(u),d=Math.cos(u),f=.6*r,p=.7*r;t.moveTo(i-h,l+s),t.arc(i,l,r,Math.PI-u,2*Math.PI+u),t.bezierCurveTo(i+h-c*f,l+s+d*f,i,n-p,i,n),t.bezierCurveTo(i,n-p,i-h+c*f,l+s+d*f,i-h,l+s),t.closePath()}}),qA=Un({type:"arrow",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.height,n=e.width,o=e.x,a=e.y,r=n/3*2;t.moveTo(o,a),t.lineTo(o+r,a+i),t.lineTo(o,a+i/4*3),t.lineTo(o-r,a+i),t.lineTo(o,a),t.closePath()}}),KA={line:function(t,e,i,n,o){o.x1=t,o.y1=e+n/2,o.x2=t+i,o.y2=e+n/2},rect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n},roundRect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n,o.r=Math.min(i,n)/4},square:function(t,e,i,n,o){var a=Math.min(i,n);o.x=t,o.y=e,o.width=a,o.height=a},circle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.r=Math.min(i,n)/2},diamond:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n},pin:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},arrow:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},triangle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n}},$A={};d({line:_M,rect:yM,roundRect:yM,square:yM,circle:sM,diamond:jA,pin:YA,arrow:qA,triangle:XA},function(t,e){$A[e]=new t});var JA=Un({type:"symbol",shape:{symbolType:"",x:0,y:0,width:0,height:0},beforeBrush:function(){var t=this.style;"pin"===this.shape.symbolType&&"inside"===t.textPosition&&(t.textPosition=["50%","40%"],t.textAlign="center",t.textVerticalAlign="middle")},buildPath:function(t,e,i){var n=e.symbolType,o=$A[n];"none"!==e.symbolType&&(o||(o=$A[n="rect"]),KA[n](e.x,e.y,e.width,e.height,o.shape),o.buildPath(t,o.shape,i))}}),QA={isDimensionStacked:pl,enableDataStack:fl,getStackedDimension:gl},tD=(Object.freeze||Object)({createList:function(t){return ml(t.getSource(),t)},getLayoutRect:ca,dataStack:QA,createScale:function(t,e){var i=e;No.isInstance(e)||h(i=new No(e),UA);var n=Hl(i);return n.setExtent(t[0],t[1]),Wl(n,i),n},mixinAxisModelCommonMethods:function(t){h(t,UA)},completeDimensions:hl,createDimensions:_A,createSymbol:Jl}),eD=1e-8;eu.prototype={constructor:eu,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,i=[e,e],n=[-e,-e],o=[],a=[],r=this.geometries,s=0;s0}),function(t){var e=t.properties,i=t.geometry,n=i.coordinates,o=[];"Polygon"===i.type&&o.push({type:"polygon",exterior:n[0],interiors:n.slice(1)}),"MultiPolygon"===i.type&&d(n,function(t){t[0]&&o.push({type:"polygon",exterior:t[0],interiors:t.slice(1)})});var a=new eu(e.name,o,e.cp);return a.properties=e,a})},nD=Bi(),oD=[0,1],aD=function(t,e,i){this.dim=t,this.scale=e,this._extent=i||[0,0],this.inverse=!1,this.onBand=!1};aD.prototype={constructor:aD,contain:function(t){var e=this._extent,i=Math.min(e[0],e[1]),n=Math.max(e[0],e[1]);return t>=i&&t<=n},containData:function(t){return this.contain(this.dataToCoord(t))},getExtent:function(){return this._extent.slice()},getPixelPrecision:function(t){return Zo(t||this.scale.getExtent(),this._extent)},setExtent:function(t,e){var i=this._extent;i[0]=t,i[1]=e},dataToCoord:function(t,e){var i=this._extent,n=this.scale;return t=n.normalize(t),this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count()),Bo(t,oD,i,e)},coordToData:function(t,e){var i=this._extent,n=this.scale;this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count());var o=Bo(t,i,oD,e);return this.scale.scale(o)},pointToData:function(t,e){},getTicksCoords:function(t){var e=(t=t||{}).tickModel||this.getTickModel(),i=au(this,e),n=f(i.ticks,function(t){return{coord:this.dataToCoord(t),tickValue:t}},this),o=e.get("alignWithLabel");return xu(this,n,i.tickCategoryInterval,o,t.clamp),n},getViewLabels:function(){return ou(this).labels},getLabelModel:function(){return this.model.getModel("axisLabel")},getTickModel:function(){return this.model.getModel("axisTick")},getBandWidth:function(){var t=this._extent,e=this.scale.getExtent(),i=e[1]-e[0]+(this.onBand?1:0);0===i&&(i=1);var n=Math.abs(t[1]-t[0]);return Math.abs(n)/i},isHorizontal:null,getRotate:null,calculateCategoryInterval:function(){return pu(this)}};var rD=iD,sD={};d(["map","each","filter","indexOf","inherits","reduce","filter","bind","curry","isArray","isString","isObject","isFunction","extend","defaults","clone","merge"],function(t){sD[t]=aw[t]});var lD={};d(["extendShape","extendPath","makePath","makeImage","mergePath","resizePath","createIcon","setHoverStyle","setLabelStyle","setTextStyle","setText","getFont","updateProps","initProps","getTransform","clipPointsByRect","clipRectByRect","Group","Image","Text","Circle","Sector","Ring","Polygon","Polyline","Rect","Line","BezierCurve","Arc","IncrementalDisplayable","CompoundPath","LinearGradient","RadialGradient","BoundingRect"],function(t){lD[t]=zM[t]}),YI.extend({type:"series.line",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,clipOverflow:!0,label:{position:"top"},lineStyle:{width:2,type:"solid"},step:!1,smooth:!1,smoothMonotone:null,symbol:"emptyCircle",symbolSize:4,symbolRotate:null,showSymbol:!0,showAllSymbol:"auto",connectNulls:!1,sampling:"none",animationEasing:"linear",progressive:0,hoverLayerThreshold:1/0}});var uD=wu.prototype,hD=wu.getSymbolSize=function(t,e){var i=t.getItemVisual(e,"symbolSize");return i instanceof Array?i.slice():[+i,+i]};uD._createSymbol=function(t,e,i,n,o){this.removeAll();var a=Jl(t,-1,-1,2,2,e.getItemVisual(i,"color"),o);a.attr({z2:100,culling:!0,scale:bu(n)}),a.drift=Su,this._symbolType=t,this.add(a)},uD.stopSymbolAnimation=function(t){this.childAt(0).stopAnimation(t)},uD.getSymbolPath=function(){return this.childAt(0)},uD.getScale=function(){return this.childAt(0).scale},uD.highlight=function(){this.childAt(0).trigger("emphasis")},uD.downplay=function(){this.childAt(0).trigger("normal")},uD.setZ=function(t,e){var i=this.childAt(0);i.zlevel=t,i.z=e},uD.setDraggable=function(t){var e=this.childAt(0);e.draggable=t,e.cursor=t?"move":"pointer"},uD.updateData=function(t,e,i){this.silent=!1;var n=t.getItemVisual(e,"symbol")||"circle",o=t.hostModel,a=hD(t,e),r=n!==this._symbolType;if(r){var s=t.getItemVisual(e,"symbolKeepAspect");this._createSymbol(n,t,e,a,s)}else(l=this.childAt(0)).silent=!1,Io(l,{scale:bu(a)},o,e);if(this._updateCommon(t,e,a,i),r){var l=this.childAt(0),u=i&&i.fadeIn,h={scale:l.scale.slice()};u&&(h.style={opacity:l.style.opacity}),l.scale=[0,0],u&&(l.style.opacity=0),To(l,h,o,e)}this._seriesModel=o};var cD=["itemStyle"],dD=["emphasis","itemStyle"],fD=["label"],pD=["emphasis","label"];uD._updateCommon=function(t,e,i,n){var o=this.childAt(0),r=t.hostModel,s=t.getItemVisual(e,"color");"image"!==o.type&&o.useStyle({strokeNoScale:!0});var l=n&&n.itemStyle,u=n&&n.hoverItemStyle,h=n&&n.symbolRotate,c=n&&n.symbolOffset,d=n&&n.labelModel,f=n&&n.hoverLabelModel,p=n&&n.hoverAnimation,g=n&&n.cursorStyle;if(!n||t.hasItemOption){var m=n&&n.itemModel?n.itemModel:t.getItemModel(e);l=m.getModel(cD).getItemStyle(["color"]),u=m.getModel(dD).getItemStyle(),h=m.getShallow("symbolRotate"),c=m.getShallow("symbolOffset"),d=m.getModel(fD),f=m.getModel(pD),p=m.getShallow("hoverAnimation"),g=m.getShallow("cursor")}else u=a({},u);var v=o.style;o.attr("rotation",(h||0)*Math.PI/180||0),c&&o.attr("position",[Vo(c[0],i[0]),Vo(c[1],i[1])]),g&&o.attr("cursor",g),o.setColor(s,n&&n.symbolInnerColor),o.setStyle(l);var y=t.getItemVisual(e,"opacity");null!=y&&(v.opacity=y);var x=t.getItemVisual(e,"liftZ"),_=o.__z2Origin;null!=x?null==_&&(o.__z2Origin=o.z2,o.z2+=x):null!=_&&(o.z2=_,o.__z2Origin=null);var w=n&&n.useNameLabel;go(v,u,d,f,{labelFetcher:r,labelDataIndex:e,defaultText:function(e,i){return w?t.getName(e):_u(t,e)},isRectText:!0,autoColor:s}),o.off("mouseover").off("mouseout").off("emphasis").off("normal"),o.hoverStyle=u,fo(o),o.__symbolOriginalScale=bu(i),p&&r.isAnimationEnabled()&&o.on("mouseover",Mu).on("mouseout",Iu).on("emphasis",Tu).on("normal",Au)},uD.fadeOut=function(t,e){var i=this.childAt(0);this.silent=i.silent=!0,!(e&&e.keepLabel)&&(i.style.text=null),Io(i,{style:{opacity:0},scale:[0,0]},this._seriesModel,this.dataIndex,t)},u(wu,tb);var gD=Du.prototype;gD.updateData=function(t,e){e=Lu(e);var i=this.group,n=t.hostModel,o=this._data,a=this._symbolCtor,r=ku(t);o||i.removeAll(),t.diff(o).add(function(n){var o=t.getItemLayout(n);if(Cu(t,o,n,e)){var s=new a(t,n,r);s.attr("position",o),t.setItemGraphicEl(n,s),i.add(s)}}).update(function(s,l){var u=o.getItemGraphicEl(l),h=t.getItemLayout(s);Cu(t,h,s,e)?(u?(u.updateData(t,s,r),Io(u,{position:h},n)):(u=new a(t,s)).attr("position",h),i.add(u),t.setItemGraphicEl(s,u)):i.remove(u)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&e.fadeOut(function(){i.remove(e)})}).execute(),this._data=t},gD.isPersistent=function(){return!0},gD.updateLayout=function(){var t=this._data;t&&t.eachItemGraphicEl(function(e,i){var n=t.getItemLayout(i);e.attr("position",n)})},gD.incrementalPrepareUpdate=function(t){this._seriesScope=ku(t),this._data=null,this.group.removeAll()},gD.incrementalUpdate=function(t,e,i){i=Lu(i);for(var n=t.start;n0&&Ru(i[o-1]);o--);for(;n0&&Ru(i[a-1]);a--);for(;o=0){var r=o.getItemGraphicEl(a);if(!r){var s=o.getItemLayout(a);if(!s)return;(r=new wu(o,a)).position=s,r.setZ(t.get("zlevel"),t.get("z")),r.ignore=isNaN(s[0])||isNaN(s[1]),r.__temp=!0,o.setItemGraphicEl(a,r),r.stopSymbolAnimation(!0),this.group.add(r)}r.highlight()}else Ar.prototype.highlight.call(this,t,e,i,n)},downplay:function(t,e,i,n){var o=t.getData(),a=zi(o,n);if(null!=a&&a>=0){var r=o.getItemGraphicEl(a);r&&(r.__temp?(o.setItemGraphicEl(a,null),this.group.remove(r)):r.downplay())}else Ar.prototype.downplay.call(this,t,e,i,n)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new MD({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e,e},_newPolygon:function(t,e){var i=this._polygon;return i&&this._lineGroup.remove(i),i=new ID({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(i),this._polygon=i,i},_updateAnimation:function(t,e,i,n,o,a){var r=this._polyline,s=this._polygon,l=t.hostModel,u=mD(this._data,t,this._stackedOnPoints,e,this._coordSys,i,this._valueOrigin,a),h=u.current,c=u.stackedOnCurrent,d=u.next,f=u.stackedOnNext;o&&(h=Yu(u.current,i,o),c=Yu(u.stackedOnCurrent,i,o),d=Yu(u.next,i,o),f=Yu(u.stackedOnNext,i,o)),r.shape.__points=u.current,r.shape.points=h,Io(r,{shape:{points:d}},l),s&&(s.setShape({points:h,stackedOnPoints:c}),Io(s,{shape:{points:d,stackedOnPoints:f}},l));for(var p=[],g=u.status,m=0;me&&(e=t[i]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,i=0;ie[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},u(kD,aD);var PD={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},ND={};ND.categoryAxis=n({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},PD),ND.valueAxis=n({boundaryGap:[0,0],splitNumber:5},PD),ND.timeAxis=r({scale:!0,min:"dataMin",max:"dataMax"},ND.valueAxis),ND.logAxis=r({scale:!0,logBase:10},ND.valueAxis);var OD=["value","category","time","log"],ED=function(t,e,i,a){d(OD,function(r){e.extend({type:t+"Axis."+r,mergeDefaultAndTheme:function(e,o){var a=this.layoutMode,s=a?ga(e):{};n(e,o.getTheme().get(r+"Axis")),n(e,this.getDefaultOption()),e.type=i(t,e),a&&pa(e,s,a)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=_l.createByAxisModel(this))},getCategories:function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:o([{},ND[r+"Axis"],a],!0)})}),lI.registerSubTypeDefaulter(t+"Axis",v(i,t))},RD=lI.extend({type:"cartesian2dAxis",axis:null,init:function(){RD.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){RD.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){RD.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});n(RD.prototype,UA);var zD={offset:0};ED("x",RD,th,zD),ED("y",RD,th,zD),lI.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var BD=ih.prototype;BD.type="grid",BD.axisPointerEnabled=!0,BD.getRect=function(){return this._rect},BD.update=function(t,e){var i=this._axesMap;this._updateScale(t,this.model),d(i.x,function(t){Wl(t.scale,t.model)}),d(i.y,function(t){Wl(t.scale,t.model)});var n={};d(i.x,function(t){nh(i,"y",t,n)}),d(i.y,function(t){nh(i,"x",t,n)}),this.resize(this.model,e)},BD.resize=function(t,e,i){function n(){d(a,function(t){var e=t.isHorizontal(),i=e?[0,o.width]:[0,o.height],n=t.inverse?1:0;t.setExtent(i[n],i[1-n]),ah(t,e?o.x:o.y)})}var o=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()});this._rect=o;var a=this._axesList;n(),!i&&t.get("containLabel")&&(d(a,function(t){if(!t.model.get("axisLabel.inside")){var e=jl(t);if(e){var i=t.isHorizontal()?"height":"width",n=t.model.get("axisLabel.margin");o[i]-=e[i]+n,"top"===t.position?o.y+=e.height+n:"left"===t.position&&(o.x+=e.width+n)}}}),n())},BD.getAxis=function(t,e){var i=this._axesMap[t];if(null!=i){if(null==e)for(var n in i)if(i.hasOwnProperty(n))return i[n];return i[e]}},BD.getAxes=function(){return this._axesList.slice()},BD.getCartesian=function(t,e){if(null!=t&&null!=e){var i="x"+t+"y"+e;return this._coordsMap[i]}w(t)&&(e=t.yAxisIndex,t=t.xAxisIndex);for(var n=0,o=this._coordsList;nu[1]?-1:1,c=["start"===o?u[0]-h*l:"end"===o?u[1]+h*l:(u[0]+u[1])/2,ph(o)?t.labelOffset+r*l:0],d=e.get("nameRotate");null!=d&&(d=d*GD/180);var f;ph(o)?n=HD(t.rotation,null!=d?d:t.rotation,r):(n=uh(t,o,d||0,u),null!=(f=t.axisNameAvailableWidth)&&(f=Math.abs(f/Math.sin(n.rotation)),!isFinite(f)&&(f=null)));var p=s.getFont(),g=e.get("nameTruncate",!0)||{},m=g.ellipsis,v=T(t.nameTruncateMaxWidth,g.maxWidth,f),y=null!=m&&null!=v?tI(i,v,p,m,{minChar:2,placeholder:g.placeholder}):i,x=e.get("tooltip",!0),_=e.mainType,w={componentType:_,name:i,$vars:["name"]};w[_+"Index"]=e.componentIndex;var b=new rM({anid:"name",__fullText:i,__truncatedText:y,position:c,rotation:n.rotation,silent:hh(e),z2:1,tooltip:x&&x.show?a({content:i,formatter:function(){return i},formatterParams:w},x):null});mo(b.style,s,{text:y,textFont:p,textFill:s.getTextColor()||e.get("axisLine.lineStyle.color"),textAlign:n.textAlign,textVerticalAlign:n.textVerticalAlign}),e.get("triggerEvent")&&(b.eventData=lh(e),b.eventData.targetType="axisName",b.eventData.name=i),this._dumbGroup.add(b),b.updateTransform(),this.group.add(b),b.decomposeTransform()}}},HD=FD.innerTextLayout=function(t,e,i){var n,o,a=Xo(e-t);return jo(a)?(o=i>0?"top":"bottom",n="center"):jo(a-GD)?(o=i>0?"bottom":"top",n="center"):(o="middle",n=a>0&&a0?"right":"left":i>0?"left":"right"),{rotation:a,textAlign:n,textVerticalAlign:o}},ZD=d,UD=v,XD=Ws({type:"axis",_axisPointer:null,axisPointerClass:null,render:function(t,e,i,n){this.axisPointerClass&&Sh(t),XD.superApply(this,"render",arguments),Dh(this,t,0,i,0,!0)},updateAxisPointer:function(t,e,i,n,o){Dh(this,t,0,i,0,!1)},remove:function(t,e){var i=this._axisPointer;i&&i.remove(e),XD.superApply(this,"remove",arguments)},dispose:function(t,e){Ch(this,e),XD.superApply(this,"dispose",arguments)}}),jD=[];XD.registerAxisPointerClass=function(t,e){jD[t]=e},XD.getAxisPointerClass=function(t){return t&&jD[t]};var YD=["axisLine","axisTickLabel","axisName"],qD=["splitArea","splitLine"],KD=XD.extend({type:"cartesianAxis",axisPointerClass:"CartesianAxisPointer",render:function(t,e,i,n){this.group.removeAll();var o=this._axisGroup;if(this._axisGroup=new tb,this.group.add(this._axisGroup),t.get("show")){var a=t.getCoordSysModel(),r=Lh(a,t),s=new FD(t,r);d(YD,s.add,s),this._axisGroup.add(s.getGroup()),d(qD,function(e){t.get(e+".show")&&this["_"+e](t,a)},this),Lo(o,this._axisGroup,t),KD.superCall(this,"render",t,e,i,n)}},remove:function(){this._splitAreaColors=null},_splitLine:function(t,e){var i=t.axis;if(!i.scale.isBlank()){var n=t.getModel("splitLine"),o=n.getModel("lineStyle"),a=o.get("color");a=y(a)?a:[a];for(var s=e.coordinateSystem.getRect(),l=i.isHorizontal(),u=0,h=i.getTicksCoords({tickModel:n}),c=[],d=[],f=o.getLineStyle(),p=0;p1){var c;"string"==typeof o?c=DD[o]:"function"==typeof o&&(c=o),c&&t.setData(n.downSample(n.mapDimension(s.dim),1/h,c,CD))}}}}}("line"));var $D=YI.extend({type:"series.__base_bar__",getInitialData:function(t,e){return ml(this.getSource(),this)},getMarkerPosition:function(t){var e=this.coordinateSystem;if(e){var i=e.dataToPoint(e.clampData(t)),n=this.getData(),o=n.getLayout("offset"),a=n.getLayout("size");return i[e.getBaseAxis().isHorizontal()?0:1]+=o+a/2,i}return[NaN,NaN]},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,large:!1,largeThreshold:400,progressive:3e3,progressiveChunkMode:"mod",itemStyle:{},emphasis:{}}});$D.extend({type:"series.bar",dependencies:["grid","polar"],brushSelector:"rect",getProgressive:function(){return!!this.get("large")&&this.get("progressive")},getProgressiveThreshold:function(){var t=this.get("progressiveThreshold"),e=this.get("largeThreshold");return e>t&&(t=e),t}});var JD=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["stroke","barBorderColor"],["lineWidth","barBorderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),QD={getBarItemStyle:function(t){var e=JD(this,t);if(this.getBorderLineDash){var i=this.getBorderLineDash();i&&(e.lineDash=i)}return e}},tC=["itemStyle","barBorderWidth"];a(No.prototype,QD),Zs({type:"bar",render:function(t,e,i){this._updateDrawMode(t);var n=t.get("coordinateSystem");return"cartesian2d"!==n&&"polar"!==n||(this._isLargeDraw?this._renderLarge(t,e,i):this._renderNormal(t,e,i)),this.group},incrementalPrepareRender:function(t,e,i){this._clear(),this._updateDrawMode(t)},incrementalRender:function(t,e,i,n){this._incrementalRenderLarge(t,e)},_updateDrawMode:function(t){var e=t.pipelineContext.large;(null==this._isLargeDraw||e^this._isLargeDraw)&&(this._isLargeDraw=e,this._clear())},_renderNormal:function(t,e,i){var n,o=this.group,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.getBaseAxis();"cartesian2d"===s.type?n=l.isHorizontal():"polar"===s.type&&(n="angle"===l.dim);var u=t.isAnimationEnabled()?t:null;a.diff(r).add(function(e){if(a.hasValue(e)){var i=a.getItemModel(e),r=iC[s.type](a,e,i),l=eC[s.type](a,e,i,r,n,u);a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,i,r,t,n,"polar"===s.type)}}).update(function(e,i){var l=r.getItemGraphicEl(i);if(a.hasValue(e)){var h=a.getItemModel(e),c=iC[s.type](a,e,h);l?Io(l,{shape:c},u,e):l=eC[s.type](a,e,h,c,n,u,!0),a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,h,c,t,n,"polar"===s.type)}else o.remove(l)}).remove(function(t){var e=r.getItemGraphicEl(t);"cartesian2d"===s.type?e&&Nh(t,u,e):e&&Oh(t,u,e)}).execute(),this._data=a},_renderLarge:function(t,e,i){this._clear(),zh(t,this.group)},_incrementalRenderLarge:function(t,e){zh(e,this.group,!0)},dispose:B,remove:function(t){this._clear(t)},_clear:function(t){var e=this.group,i=this._data;t&&t.get("animation")&&i&&!this._isLargeDraw?i.eachItemGraphicEl(function(e){"sector"===e.type?Oh(e.dataIndex,t,e):Nh(e.dataIndex,t,e)}):e.removeAll(),this._data=null}});var eC={cartesian2d:function(t,e,i,n,o,r,s){var l=new yM({shape:a({},n)});if(r){var u=l.shape,h=o?"height":"width",c={};u[h]=0,c[h]=n[h],zM[s?"updateProps":"initProps"](l,{shape:c},r,e)}return l},polar:function(t,e,i,n,o,a,s){var l=n.startAngle0?1:-1,r=n.height>0?1:-1;return{x:n.x+a*o/2,y:n.y+r*o/2,width:n.width-a*o,height:n.height-r*o}},polar:function(t,e,i){var n=t.getItemLayout(e);return{cx:n.cx,cy:n.cy,r0:n.r0,r:n.r,startAngle:n.startAngle,endAngle:n.endAngle}}},nC=Pn.extend({type:"largeBar",shape:{points:[]},buildPath:function(t,e){for(var i=e.points,n=this.__startPoint,o=this.__valueIdx,a=0;a0&&"scale"!==u){var d=o.getItemLayout(0),f=Math.max(i.getWidth(),i.getHeight())/2,p=m(r.removeClipPath,r);r.setClipPath(this._createClipPath(d.cx,d.cy,f,d.startAngle,d.clockwise,p,t))}else r.removeClipPath();this._data=o}},dispose:function(){},_createClipPath:function(t,e,i,n,o,a,r){var s=new hM({shape:{cx:t,cy:e,r0:0,r:i,startAngle:n,endAngle:n,clockwise:o}});return To(s,{shape:{endAngle:n+(o?1:-1)*Math.PI*2}},r,a),s},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var lC=function(t,e){d(e,function(e){e.update="updateView",Es(e,function(i,n){var o={};return n.eachComponent({mainType:"series",subType:t,query:i},function(t){t[e.method]&&t[e.method](i.name,i.dataIndex);var n=t.getData();n.each(function(e){var i=n.getName(e);o[i]=t.isSelected(i)||!1})}),{name:i.name,selected:o}})})},uC=function(t){return{getTargetSeries:function(e){var i={},n=R();return e.eachSeriesByType(t,function(t){t.__paletteScope=i,n.set(t.uid,t)}),n},reset:function(t,e){var i=t.getRawData(),n={},o=t.getData();o.each(function(t){var e=o.getRawIndex(t);n[e]=t}),i.each(function(e){var a=n[e],r=null!=a&&o.getItemVisual(a,"color",!0);if(r)i.setItemVisual(e,"color",r);else{var s=i.getItemModel(e).get("itemStyle.color")||t.getColorFromPalette(i.getName(e)||e+"",t.__paletteScope,i.count());i.setItemVisual(e,"color",s),null!=a&&o.setItemVisual(a,"color",s)}})}}},hC=function(t,e,i,n){var o,a,r=t.getData(),s=[],l=!1;r.each(function(i){var n,u,h,c,d=r.getItemLayout(i),f=r.getItemModel(i),p=f.getModel("label"),g=p.get("position")||f.get("emphasis.label.position"),m=f.getModel("labelLine"),v=m.get("length"),y=m.get("length2"),x=(d.startAngle+d.endAngle)/2,_=Math.cos(x),w=Math.sin(x);o=d.cx,a=d.cy;var b="inside"===g||"inner"===g;if("center"===g)n=d.cx,u=d.cy,c="center";else{var S=(b?(d.r+d.r0)/2*_:d.r*_)+o,M=(b?(d.r+d.r0)/2*w:d.r*w)+a;if(n=S+3*_,u=M+3*w,!b){var I=S+_*(v+e-d.r),T=M+w*(v+e-d.r),A=I+(_<0?-1:1)*y,D=T;n=A+(_<0?-5:5),u=D,h=[[S,M],[I,T],[A,D]]}c=b?"center":_>0?"left":"right"}var C=p.getFont(),L=p.get("rotate")?_<0?-x+Math.PI:-x:0,k=ke(t.getFormattedLabel(i,"normal")||r.getName(i),C,c,"top");l=!!L,d.label={x:n,y:u,position:g,height:k.height,len:v,len2:y,linePoints:h,textAlign:c,verticalAlign:"middle",rotation:L,inside:b},b||s.push(d.label)}),!l&&t.get("avoidLabelOverlap")&&Hh(s,o,a,e,i,n)},cC=2*Math.PI,dC=Math.PI/180,fC=function(t){return{seriesType:t,reset:function(t,e){var i=e.findComponents({mainType:"legend"});if(i&&i.length){var n=t.getData();n.filterSelf(function(t){for(var e=n.getName(t),o=0;o=0;s--){var l=2*s,u=n[l]-a/2,h=n[l+1]-r/2;if(t>=u&&e>=h&&t<=u+a&&e<=h+r)return s}return-1}}),gC=Uh.prototype;gC.isPersistent=function(){return!this._incremental},gC.updateData=function(t){this.group.removeAll();var e=new pC({rectHover:!0,cursor:"default"});e.setShape({points:t.getLayout("symbolPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},gC.updateLayout=function(t){if(!this._incremental){var e=t.getLayout("symbolPoints");this.group.eachChild(function(t){if(null!=t.startIndex){var i=2*(t.endIndex-t.startIndex),n=4*t.startIndex*2;e=new Float32Array(e.buffer,n,i)}t.setShape("points",e)})}},gC.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>2e6?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},gC.incrementalUpdate=function(t,e){var i;this._incremental?(i=new pC,this._incremental.addDisplayable(i,!0)):((i=new pC({rectHover:!0,cursor:"default",startIndex:t.start,endIndex:t.end})).incremental=!0,this.group.add(i)),i.setShape({points:e.getLayout("symbolPoints")}),this._setCommon(i,e,!!this._incremental)},gC._setCommon=function(t,e,i){var n=e.hostModel,o=e.getVisual("symbolSize");t.setShape("size",o instanceof Array?o:[o,o]),t.symbolProxy=Jl(e.getVisual("symbol"),0,0,0,0),t.setColor=t.symbolProxy.setColor;var a=t.shape.size[0]<4;t.useStyle(n.getModel("itemStyle").getItemStyle(a?["color","shadowBlur","shadowColor"]:["color"]));var r=e.getVisual("color");r&&t.setColor(r),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>=0&&(t.dataIndex=i+(t.startIndex||0))}))},gC.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},gC._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},Zs({type:"scatter",render:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).updateData(n),this._finished=!0},incrementalPrepareRender:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).incrementalPrepareUpdate(n),this._finished=!1},incrementalRender:function(t,e,i){this._symbolDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},updateTransform:function(t,e,i){var n=t.getData();if(this.group.dirty(),!this._finished||n.count()>1e4||!this._symbolDraw.isPersistent())return{update:!0};var o=AD().reset(t);o.progress&&o.progress({start:0,end:n.count()},n),this._symbolDraw.updateLayout(n)},_updateSymbolDraw:function(t,e){var i=this._symbolDraw,n=e.pipelineContext.large;return i&&n===this._isLargeDraw||(i&&i.remove(),i=this._symbolDraw=n?new Uh:new Du,this._isLargeDraw=n,this.group.removeAll()),this.group.add(i.group),i},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},dispose:function(){}}),Bs(TD("scatter","circle")),zs(AD("scatter")),u(Xh,aD),jh.prototype.getIndicatorAxes=function(){return this._indicatorAxes},jh.prototype.dataToPoint=function(t,e){var i=this._indicatorAxes[e];return this.coordToPoint(i.dataToCoord(t),e)},jh.prototype.coordToPoint=function(t,e){var i=this._indicatorAxes[e].angle;return[this.cx+t*Math.cos(i),this.cy-t*Math.sin(i)]},jh.prototype.pointToData=function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=Math.sqrt(e*e+i*i);e/=n,i/=n;for(var o,a=Math.atan2(-i,e),r=1/0,s=-1,l=0;ln[0]&&isFinite(c)&&isFinite(n[0]))}else{r.getTicks().length-1>a&&(u=i(u));var d=Math.round((n[0]+n[1])/2/u)*u,f=Math.round(a/2);r.setExtent(Go(d-f*u),Go(d+(a-f)*u)),r.setInterval(u)}})},jh.dimensions=[],jh.create=function(t,e){var i=[];return t.eachComponent("radar",function(n){var o=new jh(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeriesByType("radar",function(t){"radar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("radarIndex")||0])}),i},Fa.register("radar",jh);var mC=ND.valueAxis,vC=(Fs({type:"radar",optionUpdated:function(){var t=this.get("boundaryGap"),e=this.get("splitNumber"),o=this.get("scale"),s=this.get("axisLine"),l=this.get("axisTick"),u=this.get("axisLabel"),h=this.get("name"),c=this.get("name.show"),d=this.get("name.formatter"),p=this.get("nameGap"),g=this.get("triggerEvent"),m=f(this.get("indicator")||[],function(f){null!=f.max&&f.max>0&&!f.min?f.min=0:null!=f.min&&f.min<0&&!f.max&&(f.max=0);var m=h;if(null!=f.color&&(m=r({color:f.color},h)),f=n(i(f),{boundaryGap:t,splitNumber:e,scale:o,axisLine:s,axisTick:l,axisLabel:u,name:f.text,nameLocation:"end",nameGap:p,nameTextStyle:m,triggerEvent:g},!1),c||(f.name=""),"string"==typeof d){var v=f.name;f.name=d.replace("{value}",null!=v?v:"")}else"function"==typeof d&&(f.name=d(f.name,f));var y=a(new No(f,null,this.ecModel),UA);return y.mainType="radar",y.componentIndex=this.componentIndex,y},this);this.getIndicatorModels=function(){return m}},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"75%",startAngle:90,name:{show:!0},boundaryGap:[0,0],splitNumber:5,nameGap:15,scale:!1,shape:"polygon",axisLine:n({lineStyle:{color:"#bbb"}},mC.axisLine),axisLabel:Yh(mC.axisLabel,!1),axisTick:Yh(mC.axisTick,!1),splitLine:Yh(mC.splitLine,!0),splitArea:Yh(mC.splitArea,!0),indicator:[]}}),["axisLine","axisTickLabel","axisName"]);Ws({type:"radar",render:function(t,e,i){this.group.removeAll(),this._buildAxes(t),this._buildSplitLineAndArea(t)},_buildAxes:function(t){var e=t.coordinateSystem;d(f(e.getIndicatorAxes(),function(t){return new FD(t.model,{position:[e.cx,e.cy],rotation:t.angle,labelDirection:-1,tickDirection:-1,nameDirection:1})}),function(t){d(vC,t.add,t),this.group.add(t.getGroup())},this)},_buildSplitLineAndArea:function(t){function e(t,e,i){var n=i%e.length;return t[n]=t[n]||[],n}var i=t.coordinateSystem,n=i.getIndicatorAxes();if(n.length){var o=t.get("shape"),a=t.getModel("splitLine"),s=t.getModel("splitArea"),l=a.getModel("lineStyle"),u=s.getModel("areaStyle"),h=a.get("show"),c=s.get("show"),p=l.get("color"),g=u.get("color");p=y(p)?p:[p],g=y(g)?g:[g];var m=[],v=[];if("circle"===o)for(var x=n[0].getTicksCoords(),_=i.cx,w=i.cy,b=0;b"+f(i,function(i,n){var o=e.get(e.mapDimension(i.dim),t);return ia(i.name+" : "+o)}).join("
")},defaultOption:{zlevel:0,z:2,coordinateSystem:"radar",legendHoverLink:!0,radarIndex:0,lineStyle:{width:2,type:"solid"},label:{position:"top"},symbol:"emptyCircle",symbolSize:4}});Zs({type:"radar",render:function(t,e,n){function o(t,e){var i=t.getItemVisual(e,"symbol")||"circle",n=t.getItemVisual(e,"color");if("none"!==i){var o=qh(t.getItemVisual(e,"symbolSize")),a=Jl(i,-1,-1,2,2,n);return a.attr({style:{strokeNoScale:!0},z2:100,scale:[o[0]/2,o[1]/2]}),a}}function a(e,i,n,a,r,s){n.removeAll();for(var l=0;l"+ia(n+" : "+i)},getTooltipPosition:function(t){if(null!=t){var e=this.getData().getName(t),i=this.coordinateSystem,n=i.getRegion(e);return n&&i.dataToPoint(n.center)}},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},defaultOption:{zlevel:0,z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:.75,showLegendSymbol:!0,dataRangeHoverLink:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",areaColor:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{areaColor:"rgba(255,215,0,0.8)"}}}}),aC);var EC="\0_ec_interaction_mutex";Es({type:"takeGlobalCursor",event:"globalCursorTaken",update:"update"},function(){}),h(oc,fw);var RC={axisPointer:1,tooltip:1,brush:1};xc.prototype={constructor:xc,draw:function(t,e,i,n,o){var a="geo"===t.mainType,r=t.getData&&t.getData();a&&e.eachComponent({mainType:"series",subType:"map"},function(e){r||e.getHostGeoModel()!==t||(r=e.getData())});var s=t.coordinateSystem;this._updateBackground(s);var l=this._regionsGroup,u=this.group,h=s.scale,c={position:s.position,scale:h};!l.childAt(0)||o?u.attr(c):Io(u,c,t),l.removeAll();var f=["itemStyle"],p=["emphasis","itemStyle"],g=["label"],m=["emphasis","label"],v=R();d(s.regions,function(e){var i=v.get(e.name)||v.set(e.name,new tb),n=new MM({shape:{paths:[]}});i.add(n);var o,s=(C=t.getRegionModel(e.name)||t).getModel(f),u=C.getModel(p),c=mc(s),y=mc(u),x=C.getModel(g),_=C.getModel(m);if(r){o=r.indexOfName(e.name);var w=r.getItemVisual(o,"color",!0);w&&(c.fill=w)}d(e.geometries,function(t){if("polygon"===t.type){n.shape.paths.push(new pM({shape:{points:t.exterior}}));for(var e=0;e<(t.interiors?t.interiors.length:0);e++)n.shape.paths.push(new pM({shape:{points:t.interiors[e]}}))}}),n.setStyle(c),n.style.strokeNoScale=!0,n.culling=!0;var b=x.get("show"),S=_.get("show"),M=r&&isNaN(r.get(r.mapDimension("value"),o)),I=r&&r.getItemLayout(o);if(a||M&&(b||S)||I&&I.showLabel){var T,A=a?e.name:o;(!r||o>=0)&&(T=t);var D=new rM({position:e.center.slice(),scale:[1/h[0],1/h[1]],z2:10,silent:!0});go(D.style,D.hoverStyle={},x,_,{labelFetcher:T,labelDataIndex:A,defaultText:e.name,useInsideStyle:!1},{textAlign:"center",textVerticalAlign:"middle"}),i.add(D)}if(r)r.setItemGraphicEl(o,i);else{var C=t.getRegionModel(e.name);n.eventData={componentType:"geo",componentIndex:t.componentIndex,geoIndex:t.componentIndex,name:e.name,region:C&&C.option||{}}}(i.__regions||(i.__regions=[])).push(e),fo(i,y,{hoverSilentOnTouch:!!t.get("selectedMode")}),l.add(i)}),this._updateController(t,e,i),vc(this,t,l,i,n),yc(t,l)},remove:function(){this._regionsGroup.removeAll(),this._backgroundGroup.removeAll(),this._controller.dispose(),this._mapName&&OC.removeGraphic(this._mapName,this.uid),this._mapName=null,this._controllerHost={}},_updateBackground:function(t){var e=t.map;this._mapName!==e&&d(OC.makeGraphic(e,this.uid),function(t){this._backgroundGroup.add(t)},this),this._mapName=e},_updateController:function(t,e,i){function n(){var e={type:"geoRoam",componentType:l};return e[l+"Id"]=t.id,e}var o=t.coordinateSystem,r=this._controller,s=this._controllerHost;s.zoomLimit=t.get("scaleLimit"),s.zoom=o.getZoom(),r.enable(t.get("roam")||!1);var l=t.mainType;r.off("pan").on("pan",function(t){this._mouseDownFlag=!1,fc(s,t.dx,t.dy),i.dispatchAction(a(n(),{dx:t.dx,dy:t.dy}))},this),r.off("zoom").on("zoom",function(t){if(this._mouseDownFlag=!1,pc(s,t.scale,t.originX,t.originY),i.dispatchAction(a(n(),{zoom:t.scale,originX:t.originX,originY:t.originY})),this._updateGroup){var e=this.group.scale;this._regionsGroup.traverse(function(t){"text"===t.type&&t.attr("scale",[1/e[0],1/e[1]])})}},this),r.setPointerChecker(function(e,n,a){return o.getViewRectAfterRoam().contain(n,a)&&!gc(e,i,t)})}};var zC="__seriesMapHighDown",BC="__seriesMapCallKey";Zs({type:"map",render:function(t,e,i,n){if(!n||"mapToggleSelect"!==n.type||n.from!==this.uid){var o=this.group;if(o.removeAll(),!t.getHostGeoModel()){if(n&&"geoRoam"===n.type&&"series"===n.componentType&&n.seriesId===t.id)(a=this._mapDraw)&&o.add(a.group);else if(t.needsDrawMap){var a=this._mapDraw||new xc(i,!0);o.add(a.group),a.draw(t,e,i,this,n),this._mapDraw=a}else this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null;t.get("showLegendSymbol")&&e.getComponent("legend")&&this._renderSymbols(t,e,i)}}},remove:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null,this.group.removeAll()},dispose:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null},_renderSymbols:function(t,e,i){var n=t.originalData,o=this.group;n.each(n.mapDimension("value"),function(e,i){if(!isNaN(e)){var r=n.getItemLayout(i);if(r&&r.point){var s=r.point,l=r.offset,u=new sM({style:{fill:t.getData().getVisual("color")},shape:{cx:s[0]+9*l,cy:s[1],r:3},silent:!0,z2:8+(l?0:NM+1)});if(!l){var h=t.mainSeries.getData(),c=n.getName(i),d=h.indexOfName(c),f=n.getItemModel(i),p=f.getModel("label"),g=f.getModel("emphasis.label"),m=h.getItemGraphicEl(d),y=A(t.getFormattedLabel(d,"normal"),c),x=A(t.getFormattedLabel(d,"emphasis"),y),_=m[zC],w=Math.random();if(!_){_=m[zC]={};var b=v(_c,!0),S=v(_c,!1);m.on("mouseover",b).on("mouseout",S).on("emphasis",b).on("normal",S)}m[BC]=w,a(_,{recordVersion:w,circle:u,labelModel:p,hoverLabelModel:g,emphasisText:x,normalText:y}),wc(_,!1)}o.add(u)}}})}}),Es({type:"geoRoam",event:"geoRoam",update:"updateTransform"},function(t,e){var i=t.componentType||"series";e.eachComponent({mainType:i,query:t},function(e){var n=e.coordinateSystem;if("geo"===n.type){var o=bc(n,t,e.get("scaleLimit"));e.setCenter&&e.setCenter(o.center),e.setZoom&&e.setZoom(o.zoom),"series"===i&&d(e.seriesGroup,function(t){t.setCenter(o.center),t.setZoom(o.zoom)})}})});var VC=Q;h(Sc,Tw),Mc.prototype={constructor:Mc,type:"view",dimensions:["x","y"],setBoundingRect:function(t,e,i,n){return this._rect=new de(t,e,i,n),this._rect},getBoundingRect:function(){return this._rect},setViewRect:function(t,e,i,n){this.transformTo(t,e,i,n),this._viewRect=new de(t,e,i,n)},transformTo:function(t,e,i,n){var o=this.getBoundingRect(),a=this._rawTransformable;a.transform=o.calculateTransform(new de(t,e,i,n)),a.decomposeTransform(),this._updateTransform()},setCenter:function(t){t&&(this._center=t,this._updateCenterAndZoom())},setZoom:function(t){t=t||1;var e=this.zoomLimit;e&&(null!=e.max&&(t=Math.min(e.max,t)),null!=e.min&&(t=Math.max(e.min,t))),this._zoom=t,this._updateCenterAndZoom()},getDefaultCenter:function(){var t=this.getBoundingRect();return[t.x+t.width/2,t.y+t.height/2]},getCenter:function(){return this._center||this.getDefaultCenter()},getZoom:function(){return this._zoom||1},getRoamTransform:function(){return this._roamTransformable.getLocalTransform()},_updateCenterAndZoom:function(){var t=this._rawTransformable.getLocalTransform(),e=this._roamTransformable,i=this.getDefaultCenter(),n=this.getCenter(),o=this.getZoom();n=Q([],n,t),i=Q([],i,t),e.origin=n,e.position=[i[0]-n[0],i[1]-n[1]],e.scale=[o,o],this._updateTransform()},_updateTransform:function(){var t=this._roamTransformable,e=this._rawTransformable;e.parent=t,t.updateTransform(),e.updateTransform(),wt(this.transform||(this.transform=[]),e.transform||xt()),this._rawTransform=e.getLocalTransform(),this.invTransform=this.invTransform||[],Tt(this.invTransform,this.transform),this.decomposeTransform()},getViewRect:function(){return this._viewRect},getViewRectAfterRoam:function(){var t=this.getBoundingRect().clone();return t.applyTransform(this.transform),t},dataToPoint:function(t,e,i){var n=e?this._rawTransform:this.transform;return i=i||[],n?VC(i,t,n):G(i,t)},pointToData:function(t){var e=this.invTransform;return e?VC([],t,e):[t[0],t[1]]},convertToPixel:v(Ic,"dataToPoint"),convertFromPixel:v(Ic,"pointToData"),containPoint:function(t){return this.getViewRectAfterRoam().contain(t[0],t[1])}},h(Mc,Tw),Tc.prototype={constructor:Tc,type:"geo",dimensions:["lng","lat"],containCoord:function(t){for(var e=this.regions,i=0;ie&&(e=n.height)}this.height=e+1},getNodeById:function(t){if(this.getId()===t)return this;for(var e=0,i=this.children,n=i.length;e=0&&this.hostTree.data.setItemLayout(this.dataIndex,t,e)},getLayout:function(){return this.hostTree.data.getItemLayout(this.dataIndex)},getModel:function(t){if(!(this.dataIndex<0)){var e,i=this.hostTree,n=i.data.getItemModel(this.dataIndex),o=this.getLevelModel();return o||0!==this.children.length&&(0===this.children.length||!1!==this.isExpand)||(e=this.getLeavesModel()),n.getModel(t,(o||e||i.hostModel).getModel(t))}},getLevelModel:function(){return(this.hostTree.levelModels||[])[this.depth]},getLeavesModel:function(){return this.hostTree.leavesModel},setVisual:function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemVisual(this.dataIndex,t,e)},getVisual:function(t,e){return this.hostTree.data.getItemVisual(this.dataIndex,t,e)},getRawIndex:function(){return this.hostTree.data.getRawIndex(this.dataIndex)},getId:function(){return this.hostTree.data.getId(this.dataIndex)},isAncestorOf:function(t){for(var e=t.parentNode;e;){if(e===this)return!0;e=e.parentNode}return!1},isDescendantOf:function(t){return t!==this&&t.isAncestorOf(this)}},Vc.prototype={constructor:Vc,type:"tree",eachNode:function(t,e,i){this.root.eachNode(t,e,i)},getNodeByDataIndex:function(t){var e=this.data.getRawIndex(t);return this._nodes[e]},getNodeByName:function(t){return this.root.getNodeByName(t)},update:function(){for(var t=this.data,e=this._nodes,i=0,n=e.length;ia&&(a=t.depth)});var r=t.expandAndCollapse&&t.initialTreeDepth>=0?t.initialTreeDepth:a;return o.root.eachNode("preorder",function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=r}),o.data},getOrient:function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},formatTooltip:function(t){for(var e=this.getData().tree,i=e.root.children[0],n=e.getNodeByDataIndex(t),o=n.getValue(),a=n.name;n&&n!==i;)a=n.parentNode.name+"."+a,n=n.parentNode;return ia(a+(isNaN(o)||null==o?"":" : "+o))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0,color:"#555"},leaves:{label:{show:!0}},animationEasing:"linear",animationDuration:700,animationDurationUpdate:1e3}}),Zs({type:"tree",init:function(t,e){this._oldTree,this._mainGroup=new tb,this._controller=new oc(e.getZr()),this._controllerHost={target:this.group},this.group.add(this._mainGroup)},render:function(t,e,i,n){var o=t.getData(),a=t.layoutInfo,r=this._mainGroup,s=t.get("layout");"radial"===s?r.attr("position",[a.x+a.width/2,a.y+a.height/2]):r.attr("position",[a.x,a.y]),this._updateViewCoordSys(t),this._updateController(t,e,i);var l=this._data,u={expandAndCollapse:t.get("expandAndCollapse"),layout:s,orient:t.getOrient(),curvature:t.get("lineStyle.curveness"),symbolRotate:t.get("symbolRotate"),symbolOffset:t.get("symbolOffset"),hoverAnimation:t.get("hoverAnimation"),useNameLabel:!0,fadeIn:!0};o.diff(l).add(function(e){td(o,e)&&id(o,e,null,r,t,u)}).update(function(e,i){var n=l.getItemGraphicEl(i);td(o,e)?id(o,e,n,r,t,u):n&&nd(l,i,n,r,t,u)}).remove(function(e){var i=l.getItemGraphicEl(e);i&&nd(l,e,i,r,t,u)}).execute(),this._nodeScaleRatio=t.get("nodeScaleRatio"),this._updateNodeAndLinkScale(t),!0===u.expandAndCollapse&&o.eachItemGraphicEl(function(e,n){e.off("click").on("click",function(){i.dispatchAction({type:"treeExpandAndCollapse",seriesId:t.id,dataIndex:n})})}),this._data=o},_updateViewCoordSys:function(t){var e=t.getData(),i=[];e.each(function(t){var n=e.getItemLayout(t);!n||isNaN(n.x)||isNaN(n.y)||i.push([+n.x,+n.y])});var n=[],o=[];fn(i,n,o),o[0]-n[0]==0&&(o[0]+=1,n[0]-=1),o[1]-n[1]==0&&(o[1]+=1,n[1]-=1);var a=t.coordinateSystem=new Mc;a.zoomLimit=t.get("scaleLimit"),a.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1]),a.setCenter(t.get("center")),a.setZoom(t.get("zoom")),this.group.attr({position:a.position,scale:a.scale}),this._viewCoordSys=a},_updateController:function(t,e,i){var n=this._controller,o=this._controllerHost,a=this.group;n.setPointerChecker(function(e,n,o){var r=a.getBoundingRect();return r.applyTransform(a.transform),r.contain(n,o)&&!gc(e,i,t)}),n.enable(t.get("roam")),o.zoomLimit=t.get("scaleLimit"),o.zoom=t.coordinateSystem.getZoom(),n.off("pan").off("zoom").on("pan",function(e){fc(o,e.dx,e.dy),i.dispatchAction({seriesId:t.id,type:"treeRoam",dx:e.dx,dy:e.dy})},this).on("zoom",function(e){pc(o,e.scale,e.originX,e.originY),i.dispatchAction({seriesId:t.id,type:"treeRoam",zoom:e.scale,originX:e.originX,originY:e.originY}),this._updateNodeAndLinkScale(t)},this)},_updateNodeAndLinkScale:function(t){var e=t.getData(),i=this._getNodeGlobalScale(t),n=[i,i];e.eachItemGraphicEl(function(t,e){t.attr("scale",n)})},_getNodeGlobalScale:function(t){var e=t.coordinateSystem;if("view"!==e.type)return 1;var i=this._nodeScaleRatio,n=e.scale,o=n&&n[0]||1;return((e.getZoom()-1)*i+1)/o},dispose:function(){this._controller&&this._controller.dispose(),this._controllerHost={}},remove:function(){this._mainGroup.removeAll(),this._data=null}}),Es({type:"treeExpandAndCollapse",event:"treeExpandAndCollapse",update:"update"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=t.dataIndex,n=e.getData().tree.getNodeByDataIndex(i);n.isExpand=!n.isExpand})}),Es({type:"treeRoam",event:"treeRoam",update:"none"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=bc(e.coordinateSystem,t);e.setCenter&&e.setCenter(i.center),e.setZoom&&e.setZoom(i.zoom)})});Bs(TD("tree","circle")),zs(function(t,e){t.eachSeriesByType("tree",function(t){sd(t,e)})}),YI.extend({type:"series.treemap",layoutMode:"box",dependencies:["grid","polar"],_viewRoot:null,defaultOption:{progressive:0,hoverLayerThreshold:1/0,left:"center",top:"middle",right:null,bottom:null,width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",borderColor:"rgba(255,255,255,0.7)",borderWidth:1,shadowColor:"rgba(150,150,150,1)",shadowBlur:3,shadowOffsetX:0,shadowOffsetY:0,textStyle:{color:"#fff"}},emphasis:{textStyle:{}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",ellipsis:!0},upperLabel:{show:!1,position:[0,"50%"],height:20,color:"#fff",ellipsis:!0,verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],color:"#fff",ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},getInitialData:function(t,e){var i={name:t.name,children:t.data};dd(i);var n=t.levels||[];n=t.levels=fd(n,e);var o={};return o.levels=n,Vc.createTree(i,this,o).data},optionUpdated:function(){this.resetViewRoot()},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=ta(y(i)?i[0]:i);return ia(e.getName(t)+": "+n)},getDataParams:function(t){var e=YI.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=cd(i,this),e},setLayoutInfo:function(t){this.layoutInfo=this.layoutInfo||{},a(this.layoutInfo,t)},mapIdToIndex:function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=R(),this._idIndexMapCount=0);var i=e.get(t);return null==i&&e.set(t,i=this._idIndexMapCount++),i},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var UC=5;pd.prototype={constructor:pd,render:function(t,e,i,n){var o=t.getModel("breadcrumb"),a=this.group;if(a.removeAll(),o.get("show")&&i){var r=o.getModel("itemStyle"),s=r.getModel("textStyle"),l={pos:{left:o.get("left"),right:o.get("right"),top:o.get("top"),bottom:o.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:o.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(i,l,s),this._renderContent(t,l,r,s,n),da(a,l.pos,l.box)}},_prepare:function(t,e,i){for(var n=t;n;n=n.parentNode){var o=n.getModel().get("name"),a=i.getTextRect(o),r=Math.max(a.width+16,e.emptyItemWidth);e.totalWidth+=r+8,e.renderList.push({node:n,text:o,width:r})}},_renderContent:function(t,e,i,n,o){for(var a=0,s=e.emptyItemWidth,l=t.get("breadcrumb.height"),u=ha(e.pos,e.box),h=e.totalWidth,c=e.renderList,d=c.length-1;d>=0;d--){var f=c[d],p=f.node,g=f.width,m=f.text;h>u.width&&(h-=g-s,g=s,m=null);var y=new pM({shape:{points:gd(a,0,g,l,d===c.length-1,0===d)},style:r(i.getItemStyle(),{lineJoin:"bevel",text:m,textFill:n.getTextColor(),textFont:n.getFont()}),z:10,onclick:v(o,p)});this.group.add(y),md(y,t,p),a+=g+8}},remove:function(){this.group.removeAll()}};var XC=m,jC=tb,YC=yM,qC=d,KC=["label"],$C=["emphasis","label"],JC=["upperLabel"],QC=["emphasis","upperLabel"],tL=10,eL=1,iL=2,nL=Qb([["fill","color"],["stroke","strokeColor"],["lineWidth","strokeWidth"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),oL=function(t){var e=nL(t);return e.stroke=e.fill=e.lineWidth=null,e};Zs({type:"treemap",init:function(t,e){this._containerGroup,this._storage={nodeGroup:[],background:[],content:[]},this._oldTree,this._breadcrumb,this._controller,this._state="ready"},render:function(t,e,i,n){if(!(l(e.findComponents({mainType:"series",subType:"treemap",query:n}),t)<0)){this.seriesModel=t,this.api=i,this.ecModel=e;var o=ld(n,["treemapZoomToNode","treemapRootToNode"],t),a=n&&n.type,r=t.layoutInfo,s=!this._oldTree,u=this._storage,h="treemapRootToNode"===a&&o&&u?{rootNodeGroup:u.nodeGroup[o.node.getRawIndex()],direction:n.direction}:null,c=this._giveContainerGroup(r),d=this._doRender(c,t,h);s||a&&"treemapZoomToNode"!==a&&"treemapRootToNode"!==a?d.renderFinally():this._doAnimation(c,d,t,h),this._resetController(i),this._renderBreadcrumb(t,i,o)}},_giveContainerGroup:function(t){var e=this._containerGroup;return e||(e=this._containerGroup=new jC,this._initEvents(e),this.group.add(e)),e.attr("position",[t.x,t.y]),e},_doRender:function(t,e,i){function n(t,e,i,o,a){function r(t){return t.getId()}function s(r,s){var l=null!=r?t[r]:null,u=null!=s?e[s]:null,c=h(l,u,i,a);c&&n(l&&l.viewChildren||[],u&&u.viewChildren||[],c,o,a+1)}o?(e=t,qC(t,function(t,e){!t.isRemoved()&&s(e,e)})):new Xs(e,t,r,r).add(s).update(s).remove(v(s,null)).execute()}var o=e.getData().tree,a=this._oldTree,r={nodeGroup:[],background:[],content:[]},s={nodeGroup:[],background:[],content:[]},l=this._storage,u=[],h=v(yd,e,s,l,i,r,u);n(o.root?[o.root]:[],a&&a.root?[a.root]:[],t,o===a||!a,0);var c=function(t){var e={nodeGroup:[],background:[],content:[]};return t&&qC(t,function(t,i){var n=e[i];qC(t,function(t){t&&(n.push(t),t.__tmWillDelete=1)})}),e}(l);return this._oldTree=o,this._storage=s,{lastsForAnimation:r,willDeleteEls:c,renderFinally:function(){qC(c,function(t){qC(t,function(t){t.parent&&t.parent.remove(t)})}),qC(u,function(t){t.invisible=!0,t.dirty()})}}},_doAnimation:function(t,e,i,n){if(i.get("animation")){var o=i.get("animationDurationUpdate"),r=i.get("animationEasing"),s=vd();qC(e.willDeleteEls,function(t,e){qC(t,function(t,i){if(!t.invisible){var a,l=t.parent;if(n&&"drillDown"===n.direction)a=l===n.rootNodeGroup?{shape:{x:0,y:0,width:l.__tmNodeWidth,height:l.__tmNodeHeight},style:{opacity:0}}:{style:{opacity:0}};else{var u=0,h=0;l.__tmWillDelete||(u=l.__tmNodeWidth/2,h=l.__tmNodeHeight/2),a="nodeGroup"===e?{position:[u,h],style:{opacity:0}}:{shape:{x:u,y:h,width:0,height:0},style:{opacity:0}}}a&&s.add(t,a,o,r)}})}),qC(this._storage,function(t,i){qC(t,function(t,n){var l=e.lastsForAnimation[i][n],u={};l&&("nodeGroup"===i?l.old&&(u.position=t.position.slice(),t.attr("position",l.old)):(l.old&&(u.shape=a({},t.shape),t.setShape(l.old)),l.fadein?(t.setStyle("opacity",0),u.style={opacity:1}):1!==t.style.opacity&&(u.style={opacity:1})),s.add(t,u,o,r))})},this),this._state="animating",s.done(XC(function(){this._state="ready",e.renderFinally()},this)).start()}},_resetController:function(t){var e=this._controller;e||((e=this._controller=new oc(t.getZr())).enable(this.seriesModel.get("roam")),e.on("pan",XC(this._onPan,this)),e.on("zoom",XC(this._onZoom,this)));var i=new de(0,0,t.getWidth(),t.getHeight());e.setPointerChecker(function(t,e,n){return i.contain(e,n)})},_clearController:function(){var t=this._controller;t&&(t.dispose(),t=null)},_onPan:function(t){if("animating"!==this._state&&(Math.abs(t.dx)>3||Math.abs(t.dy)>3)){var e=this.seriesModel.getData().tree.root;if(!e)return;var i=e.getLayout();if(!i)return;this.api.dispatchAction({type:"treemapMove",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:i.x+t.dx,y:i.y+t.dy,width:i.width,height:i.height}})}},_onZoom:function(t){var e=t.originX,i=t.originY;if("animating"!==this._state){var n=this.seriesModel.getData().tree.root;if(!n)return;var o=n.getLayout();if(!o)return;var a=new de(o.x,o.y,o.width,o.height),r=this.seriesModel.layoutInfo;e-=r.x,i-=r.y;var s=xt();St(s,s,[-e,-i]),It(s,s,[t.scale,t.scale]),St(s,s,[e,i]),a.applyTransform(s),this.api.dispatchAction({type:"treemapRender",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:a.x,y:a.y,width:a.width,height:a.height}})}},_initEvents:function(t){t.on("click",function(t){if("ready"===this._state){var e=this.seriesModel.get("nodeClick",!0);if(e){var i=this.findTarget(t.offsetX,t.offsetY);if(i){var n=i.node;if(n.getLayout().isLeafRoot)this._rootToNode(i);else if("zoomToNode"===e)this._zoomToNode(i);else if("link"===e){var o=n.hostTree.data.getItemModel(n.dataIndex),a=o.get("link",!0),r=o.get("target",!0)||"blank";a&&window.open(a,r)}}}}},this)},_renderBreadcrumb:function(t,e,i){i||(i=null!=t.get("leafDepth",!0)?{node:t.getViewRoot()}:this.findTarget(e.getWidth()/2,e.getHeight()/2))||(i={node:t.getData().tree.root}),(this._breadcrumb||(this._breadcrumb=new pd(this.group))).render(t,e,i.node,XC(function(e){"animating"!==this._state&&(hd(t.getViewRoot(),e)?this._rootToNode({node:e}):this._zoomToNode({node:e}))},this))},remove:function(){this._clearController(),this._containerGroup&&this._containerGroup.removeAll(),this._storage={nodeGroup:[],background:[],content:[]},this._state="ready",this._breadcrumb&&this._breadcrumb.remove()},dispose:function(){this._clearController()},_zoomToNode:function(t){this.api.dispatchAction({type:"treemapZoomToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},_rootToNode:function(t){this.api.dispatchAction({type:"treemapRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},findTarget:function(t,e){var i;return this.seriesModel.getViewRoot().eachNode({attr:"viewChildren",order:"preorder"},function(n){var o=this._storage.background[n.getRawIndex()];if(o){var a=o.transformCoordToLocal(t,e),r=o.shape;if(!(r.x<=a[0]&&a[0]<=r.x+r.width&&r.y<=a[1]&&a[1]<=r.y+r.height))return!1;i={node:n,offsetX:a[0],offsetY:a[1]}}},this),i}});for(var aL=["treemapZoomToNode","treemapRender","treemapMove"],rL=0;rL=0&&t.call(e,i[o],o)},TL.eachEdge=function(t,e){for(var i=this.edges,n=i.length,o=0;o=0&&i[o].node1.dataIndex>=0&&i[o].node2.dataIndex>=0&&t.call(e,i[o],o)},TL.breadthFirstTraverse=function(t,e,i,n){if(Jd.isInstance(e)||(e=this._nodesMap[$d(e)]),e){for(var o="out"===i?"outEdges":"in"===i?"inEdges":"edges",a=0;a=0&&i.node2.dataIndex>=0});for(var o=0,a=n.length;o=0&&this[t][e].setItemVisual(this.dataIndex,i,n)},getVisual:function(i,n){return this[t][e].getItemVisual(this.dataIndex,i,n)},setLayout:function(i,n){this.dataIndex>=0&&this[t][e].setItemLayout(this.dataIndex,i,n)},getLayout:function(){return this[t][e].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[t][e].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[t][e].getRawIndex(this.dataIndex)}}};h(Jd,AL("hostGraph","data")),h(Qd,AL("hostGraph","edgeData")),IL.Node=Jd,IL.Edge=Qd,Yi(Jd),Yi(Qd);var DL=function(t,e,i,n,o){for(var a=new IL(n),r=0;r "+f)),h++)}var p,g=i.get("coordinateSystem");if("cartesian2d"===g||"polar"===g)p=ml(t,i);else{var m=Fa.get(g),v=m&&"view"!==m.type?m.dimensions||[]:[];l(v,"value")<0&&v.concat(["value"]);var y=_A(t,{coordDimensions:v});(p=new vA(y,i)).initData(t)}var x=new vA(["value"],i);return x.initData(u,s),o&&o(p,x),kc({mainData:p,struct:a,structAttr:"graph",datas:{node:p,edge:x},datasAttr:{node:"data",edge:"edgeData"}}),a.update(),a},CL=Hs({type:"series.graph",init:function(t){CL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this._categoriesData},this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeOption:function(t){CL.superApply(this,"mergeOption",arguments),this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeDefaultAndTheme:function(t){CL.superApply(this,"mergeDefaultAndTheme",arguments),Ci(t,["edgeLabel"],["show"])},getInitialData:function(t,e){var i=t.edges||t.links||[],n=t.data||t.nodes||[],o=this;if(n&&i)return DL(n,i,this,!0,function(t,i){function n(t){return(t=this.parsePath(t))&&"label"===t[0]?r:t&&"emphasis"===t[0]&&"label"===t[1]?l:this.parentModel}t.wrapMethod("getItemModel",function(t){var e=o._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t});var a=o.getModel("edgeLabel"),r=new No({label:a.option},a.parentModel,e),s=o.getModel("emphasis.edgeLabel"),l=new No({emphasis:{label:s.option}},s.parentModel,e);i.wrapMethod("getItemModel",function(t){return t.customizeGetParent(n),t})}).data},getGraph:function(){return this.getData().graph},getEdgeData:function(){return this.getGraph().edgeData},getCategoriesData:function(){return this._categoriesData},formatTooltip:function(t,e,i){if("edge"===i){var n=this.getData(),o=this.getDataParams(t,i),a=n.graph.getEdgeByIndex(t),r=n.getName(a.node1.dataIndex),s=n.getName(a.node2.dataIndex),l=[];return null!=r&&l.push(r),null!=s&&l.push(s),l=ia(l.join(" > ")),o.value&&(l+=" : "+ia(o.value)),l}return CL.superApply(this,"formatTooltip",arguments)},_updateCategoriesData:function(){var t=f(this.option.categories||[],function(t){return null!=t.value?t:a({value:0},t)}),e=new vA(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray(function(t){return e.getItemModel(t,!0)})},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},isAnimationEnabled:function(){return CL.superCall(this,"isAnimationEnabled")&&!("force"===this.get("layout")&&this.get("force.layoutAnimation"))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,hoverAnimation:!0,layout:null,focusNodeAdjacency:!1,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle"},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,curveness:0,opacity:.5},emphasis:{label:{show:!0}}}}),LL=_M.prototype,kL=bM.prototype,PL=Un({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){(tf(e)?LL:kL).buildPath(t,e)},pointAt:function(t){return tf(this.shape)?LL.pointAt.call(this,t):kL.pointAt.call(this,t)},tangentAt:function(t){var e=this.shape,i=tf(e)?[e.x2-e.x1,e.y2-e.y1]:kL.tangentAt.call(this,t);return q(i,i)}}),NL=["fromSymbol","toSymbol"],OL=rf.prototype;OL.beforeUpdate=function(){var t=this,e=t.childOfName("fromSymbol"),i=t.childOfName("toSymbol"),n=t.childOfName("label");if(e||i||!n.ignore){for(var o=1,a=this.parent;a;)a.scale&&(o/=a.scale[0]),a=a.parent;var r=t.childOfName("line");if(this.__dirty||r.__dirty){var s=r.shape.percent,l=r.pointAt(0),u=r.pointAt(s),h=U([],u,l);if(q(h,h),e&&(e.attr("position",l),c=r.tangentAt(0),e.attr("rotation",Math.PI/2-Math.atan2(c[1],c[0])),e.attr("scale",[o*s,o*s])),i){i.attr("position",u);var c=r.tangentAt(1);i.attr("rotation",-Math.PI/2-Math.atan2(c[1],c[0])),i.attr("scale",[o*s,o*s])}if(!n.ignore){n.attr("position",u);var d,f,p,g=5*o;if("end"===n.__position)d=[h[0]*g+u[0],h[1]*g+u[1]],f=h[0]>.8?"left":h[0]<-.8?"right":"center",p=h[1]>.8?"top":h[1]<-.8?"bottom":"middle";else if("middle"===n.__position){var m=s/2,v=[(c=r.tangentAt(m))[1],-c[0]],y=r.pointAt(m);v[1]>0&&(v[0]=-v[0],v[1]=-v[1]),d=[y[0]+v[0]*g,y[1]+v[1]*g],f="center",p="bottom";var x=-Math.atan2(c[1],c[0]);u[0].8?"right":h[0]<-.8?"left":"center",p=h[1]>.8?"bottom":h[1]<-.8?"top":"middle";n.attr({style:{textVerticalAlign:n.__verticalAlign||p,textAlign:n.__textAlign||f},position:d,scale:[o,o]})}}}},OL._createLine=function(t,e,i){var n=t.hostModel,o=of(t.getItemLayout(e));o.shape.percent=0,To(o,{shape:{percent:1}},n,e),this.add(o);var a=new rM({name:"label",lineLabelOriginalOpacity:1});this.add(a),d(NL,function(i){var n=nf(i,t,e);this.add(n),this[ef(i)]=t.getItemVisual(e,i)},this),this._updateCommonStl(t,e,i)},OL.updateData=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=t.getItemLayout(e),r={shape:{}};af(r.shape,a),Io(o,r,n,e),d(NL,function(i){var n=t.getItemVisual(e,i),o=ef(i);if(this[o]!==n){this.remove(this.childOfName(i));var a=nf(i,t,e);this.add(a)}this[o]=n},this),this._updateCommonStl(t,e,i)},OL._updateCommonStl=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=i&&i.lineStyle,s=i&&i.hoverLineStyle,l=i&&i.labelModel,u=i&&i.hoverLabelModel;if(!i||t.hasItemOption){var h=t.getItemModel(e);a=h.getModel("lineStyle").getLineStyle(),s=h.getModel("emphasis.lineStyle").getLineStyle(),l=h.getModel("label"),u=h.getModel("emphasis.label")}var c=t.getItemVisual(e,"color"),f=D(t.getItemVisual(e,"opacity"),a.opacity,1);o.useStyle(r({strokeNoScale:!0,fill:"none",stroke:c,opacity:f},a)),o.hoverStyle=s,d(NL,function(t){var e=this.childOfName(t);e&&(e.setColor(c),e.setStyle({opacity:f}))},this);var p,g,m=l.getShallow("show"),v=u.getShallow("show"),y=this.childOfName("label");if((m||v)&&(p=c||"#000",null==(g=n.getFormattedLabel(e,"normal",t.dataType)))){var x=n.getRawValue(e);g=null==x?t.getName(e):isFinite(x)?Go(x):x}var _=m?g:null,w=v?A(n.getFormattedLabel(e,"emphasis",t.dataType),g):null,b=y.style;null==_&&null==w||(mo(y.style,l,{text:_},{autoColor:p}),y.__textAlign=b.textAlign,y.__verticalAlign=b.textVerticalAlign,y.__position=l.get("position")||"middle"),y.hoverStyle=null!=w?{text:w,textFill:u.getTextColor(!0),fontStyle:u.getShallow("fontStyle"),fontWeight:u.getShallow("fontWeight"),fontSize:u.getShallow("fontSize"),fontFamily:u.getShallow("fontFamily")}:{text:null},y.ignore=!m&&!v,fo(this)},OL.highlight=function(){this.trigger("emphasis")},OL.downplay=function(){this.trigger("normal")},OL.updateLayout=function(t,e){this.setLinePoints(t.getItemLayout(e))},OL.setLinePoints=function(t){var e=this.childOfName("line");af(e.shape,t),e.dirty()},u(rf,tb);var EL=sf.prototype;EL.isPersistent=function(){return!0},EL.updateData=function(t){var e=this,i=e.group,n=e._lineData;e._lineData=t,n||i.removeAll();var o=hf(t);t.diff(n).add(function(i){lf(e,t,i,o)}).update(function(i,a){uf(e,n,t,a,i,o)}).remove(function(t){i.remove(n.getItemGraphicEl(t))}).execute()},EL.updateLayout=function(){var t=this._lineData;t&&t.eachItemGraphicEl(function(e,i){e.updateLayout(t,i)},this)},EL.incrementalPrepareUpdate=function(t){this._seriesScope=hf(t),this._lineData=null,this.group.removeAll()},EL.incrementalUpdate=function(t,e){for(var i=t.start;i=o/3?1:2),l=e.y-n(r)*a*(a>=o/3?1:2);r=e.angle-Math.PI/2,t.moveTo(s,l),t.lineTo(e.x+i(r)*a,e.y+n(r)*a),t.lineTo(e.x+i(e.angle)*o,e.y+n(e.angle)*o),t.lineTo(e.x-i(r)*a,e.y-n(r)*a),t.lineTo(s,l)}}),YL=2*Math.PI,qL=(Ar.extend({type:"gauge",render:function(t,e,i){this.group.removeAll();var n=t.get("axisLine.lineStyle.color"),o=Sf(t,i);this._renderMain(t,e,i,n,o)},dispose:function(){},_renderMain:function(t,e,i,n,o){for(var a=this.group,r=t.getModel("axisLine").getModel("lineStyle"),s=t.get("clockwise"),l=-t.get("startAngle")/180*Math.PI,u=-t.get("endAngle")/180*Math.PI,h=(u-l)%YL,c=l,d=r.get("width"),f=0;f=t&&(0===e?0:n[e-1][0]).4?"bottom":"middle",textAlign:A<-.4?"left":A>.4?"right":"center"},{autoColor:P}),silent:!0}))}if(g.get("show")&&T!==v){for(var N=0;N<=y;N++){var A=Math.cos(w),D=Math.sin(w),O=new _M({shape:{x1:A*c+u,y1:D*c+h,x2:A*(c-_)+u,y2:D*(c-_)+h},silent:!0,style:I});"auto"===I.stroke&&O.setStyle({stroke:n((T+N/y)/v)}),l.add(O),w+=S}w-=S}else w+=b}},_renderPointer:function(t,e,i,n,o,a,r,s){var l=this.group,u=this._data;if(t.get("pointer.show")){var h=[+t.get("min"),+t.get("max")],c=[a,r],d=t.getData(),f=d.mapDimension("value");d.diff(u).add(function(e){var i=new jL({shape:{angle:a}});To(i,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(i),d.setItemGraphicEl(e,i)}).update(function(e,i){var n=u.getItemGraphicEl(i);Io(n,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(n),d.setItemGraphicEl(e,n)}).remove(function(t){var e=u.getItemGraphicEl(t);l.remove(e)}).execute(),d.eachItemGraphicEl(function(t,e){var i=d.getItemModel(e),a=i.getModel("pointer");t.setShape({x:o.cx,y:o.cy,width:Vo(a.get("width"),o.r),r:Vo(a.get("length"),o.r)}),t.useStyle(i.getModel("itemStyle").getItemStyle()),"auto"===t.style.fill&&t.setStyle("fill",n(Bo(d.get(f,e),h,[0,1],!0))),fo(t,i.getModel("emphasis.itemStyle").getItemStyle())}),this._data=d}else u&&u.eachItemGraphicEl(function(t){l.remove(t)})},_renderTitle:function(t,e,i,n,o){var a=t.getData(),r=a.mapDimension("value"),s=t.getModel("title");if(s.get("show")){var l=s.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=+t.get("min"),d=+t.get("max"),f=n(Bo(t.getData().get(r,0),[c,d],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},s,{x:u,y:h,text:a.getName(0),textAlign:"center",textVerticalAlign:"middle"},{autoColor:f,forceRich:!0})}))}},_renderDetail:function(t,e,i,n,o){var a=t.getModel("detail"),r=+t.get("min"),s=+t.get("max");if(a.get("show")){var l=a.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=Vo(a.get("width"),o.r),d=Vo(a.get("height"),o.r),f=t.getData(),p=f.get(f.mapDimension("value"),0),g=n(Bo(p,[r,s],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},a,{x:u,y:h,text:Mf(p,a.get("formatter")),textWidth:isNaN(c)?null:c,textHeight:isNaN(d)?null:d,textAlign:"center",textVerticalAlign:"middle"},{autoColor:g,forceRich:!0})}))}}}),Hs({type:"series.funnel",init:function(t){qL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()},this._defaultLabelLine(t)},getInitialData:function(t,e){return oC(this,["value"])},_defaultLabelLine:function(t){Ci(t,"labelLine",["show"]);var e=t.labelLine,i=t.emphasis.labelLine;e.show=e.show&&t.label.show,i.show=i.show&&t.emphasis.label.show},getDataParams:function(t){var e=this.getData(),i=qL.superCall(this,"getDataParams",t),n=e.mapDimension("value"),o=e.getSum(n);return i.percent=o?+(e.get(n,t)/o*100).toFixed(2):0,i.$vars.push("percent"),i},defaultOption:{zlevel:0,z:2,legendHoverLink:!0,left:80,top:60,right:80,bottom:60,minSize:"0%",maxSize:"100%",sort:"descending",gap:0,funnelAlign:"center",label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:"solid"}},itemStyle:{borderColor:"#fff",borderWidth:1},emphasis:{label:{show:!0}}}})),KL=If.prototype,$L=["itemStyle","opacity"];KL.updateData=function(t,e,i){var n=this.childAt(0),o=t.hostModel,a=t.getItemModel(e),s=t.getItemLayout(e),l=t.getItemModel(e).get($L);l=null==l?1:l,n.useStyle({}),i?(n.setShape({points:s.points}),n.setStyle({opacity:0}),To(n,{style:{opacity:l}},o,e)):Io(n,{style:{opacity:l},shape:{points:s.points}},o,e);var u=a.getModel("itemStyle"),h=t.getItemVisual(e,"color");n.setStyle(r({lineJoin:"round",fill:h},u.getItemStyle(["opacity"]))),n.hoverStyle=u.getModel("emphasis").getItemStyle(),this._updateLabel(t,e),fo(this)},KL._updateLabel=function(t,e){var i=this.childAt(1),n=this.childAt(2),o=t.hostModel,a=t.getItemModel(e),r=t.getItemLayout(e).label,s=t.getItemVisual(e,"color");Io(i,{shape:{points:r.linePoints||r.linePoints}},o,e),Io(n,{style:{x:r.x,y:r.y}},o,e),n.attr({rotation:r.rotation,origin:[r.x,r.y],z2:10});var l=a.getModel("label"),u=a.getModel("emphasis.label"),h=a.getModel("labelLine"),c=a.getModel("emphasis.labelLine"),s=t.getItemVisual(e,"color");go(n.style,n.hoverStyle={},l,u,{labelFetcher:t.hostModel,labelDataIndex:e,defaultText:t.getName(e),autoColor:s,useInsideStyle:!!r.inside},{textAlign:r.textAlign,textVerticalAlign:r.verticalAlign}),n.ignore=n.normalIgnore=!l.get("show"),n.hoverIgnore=!u.get("show"),i.ignore=i.normalIgnore=!h.get("show"),i.hoverIgnore=!c.get("show"),i.setStyle({stroke:s}),i.setStyle(h.getModel("lineStyle").getLineStyle()),i.hoverStyle=c.getModel("lineStyle").getLineStyle()},u(If,tb);Ar.extend({type:"funnel",render:function(t,e,i){var n=t.getData(),o=this._data,a=this.group;n.diff(o).add(function(t){var e=new If(n,t);n.setItemGraphicEl(t,e),a.add(e)}).update(function(t,e){var i=o.getItemGraphicEl(e);i.updateData(n,t),a.add(i),n.setItemGraphicEl(t,i)}).remove(function(t){var e=o.getItemGraphicEl(t);a.remove(e)}).execute(),this._data=n},remove:function(){this.group.removeAll(),this._data=null},dispose:function(){}});Bs(uC("funnel")),zs(function(t,e,i){t.eachSeriesByType("funnel",function(t){var i=t.getData(),n=i.mapDimension("value"),o=t.get("sort"),a=Tf(t,e),r=Af(i,o),s=[Vo(t.get("minSize"),a.width),Vo(t.get("maxSize"),a.width)],l=i.getDataExtent(n),u=t.get("min"),h=t.get("max");null==u&&(u=Math.min(l[0],0)),null==h&&(h=l[1]);var c=t.get("funnelAlign"),d=t.get("gap"),f=(a.height-d*(i.count()-1))/i.count(),p=a.y,g=function(t,e){var o,r=Bo(i.get(n,t)||0,[u,h],s,!0);switch(c){case"left":o=a.x;break;case"center":o=a.x+(a.width-r)/2;break;case"right":o=a.x+a.width-r}return[[o,e],[o+r,e]]};"ascending"===o&&(f=-f,d=-d,p+=a.height,r=r.reverse());for(var m=0;ma&&(e[1-n]=e[n]+h.sign*a),e},tk=d,ek=Math.min,ik=Math.max,nk=Math.floor,ok=Math.ceil,ak=Go,rk=Math.PI;Nf.prototype={type:"parallel",constructor:Nf,_init:function(t,e,i){var n=t.dimensions,o=t.parallelAxisIndex;tk(n,function(t,i){var n=o[i],a=e.getComponent("parallelAxis",n),r=this._axesMap.set(t,new JL(t,Hl(a),[0,0],a.get("type"),n)),s="category"===r.type;r.onBand=s&&a.get("boundaryGap"),r.inverse=a.get("inverse"),a.axis=r,r.model=a,r.coordinateSystem=a.coordinateSystem=this},this)},update:function(t,e){this._updateAxesFromSeries(this._model,t)},containPoint:function(t){var e=this._makeLayoutInfo(),i=e.axisBase,n=e.layoutBase,o=e.pixelDimIndex,a=t[1-o],r=t[o];return a>=i&&a<=i+e.axisLength&&r>=n&&r<=n+e.layoutLength},getModel:function(){return this._model},_updateAxesFromSeries:function(t,e){e.eachSeries(function(i){if(t.contains(i,e)){var n=i.getData();tk(this.dimensions,function(t){var e=this._axesMap.get(t);e.scale.unionExtentFromData(n,n.mapDimension(t)),Wl(e.scale,e.model)},this)}},this)},resize:function(t,e){this._rect=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()}),this._layoutAxes()},getRect:function(){return this._rect},_makeLayoutInfo:function(){var t,e=this._model,i=this._rect,n=["x","y"],o=["width","height"],a=e.get("layout"),r="horizontal"===a?0:1,s=i[o[r]],l=[0,s],u=this.dimensions.length,h=Of(e.get("axisExpandWidth"),l),c=Of(e.get("axisExpandCount")||0,[0,u]),d=e.get("axisExpandable")&&u>3&&u>c&&c>1&&h>0&&s>0,f=e.get("axisExpandWindow");f?(t=Of(f[1]-f[0],l),f[1]=f[0]+t):(t=Of(h*(c-1),l),(f=[h*(e.get("axisExpandCenter")||nk(u/2))-t/2])[1]=f[0]+t);var p=(s-t)/(u-c);p<3&&(p=0);var g=[nk(ak(f[0]/h,1))+1,ok(ak(f[1]/h,1))-1],m=p/h*f[0];return{layout:a,pixelDimIndex:r,layoutBase:i[n[r]],layoutLength:s,axisBase:i[n[1-r]],axisLength:i[o[1-r]],axisExpandable:d,axisExpandWidth:h,axisCollapseWidth:p,axisExpandWindow:f,axisCount:u,winInnerIndices:g,axisExpandWindow0Pos:m}},_layoutAxes:function(){var t=this._rect,e=this._axesMap,i=this.dimensions,n=this._makeLayoutInfo(),o=n.layout;e.each(function(t){var e=[0,n.axisLength],i=t.inverse?1:0;t.setExtent(e[i],e[1-i])}),tk(i,function(e,i){var a=(n.axisExpandable?Rf:Ef)(i,n),r={horizontal:{x:a.position,y:n.axisLength},vertical:{x:0,y:a.position}},s={horizontal:rk/2,vertical:0},l=[r[o].x+t.x,r[o].y+t.y],u=s[o],h=xt();Mt(h,h,u),St(h,h,l),this._axesLayout[e]={position:l,rotation:u,transform:h,axisNameAvailableWidth:a.axisNameAvailableWidth,axisLabelShow:a.axisLabelShow,nameTruncateMaxWidth:a.nameTruncateMaxWidth,tickDirection:1,labelDirection:1}},this)},getAxis:function(t){return this._axesMap.get(t)},dataToPoint:function(t,e){return this.axisCoordToPoint(this._axesMap.get(e).dataToCoord(t),e)},eachActiveState:function(t,e,i,n){null==i&&(i=0),null==n&&(n=t.count());var o=this._axesMap,a=this.dimensions,r=[],s=[];d(a,function(e){r.push(t.mapDimension(e)),s.push(o.get(e).model)});for(var l=this.hasAxisBrushed(),u=i;uo*(1-h[0])?(l="jump",r=s-o*(1-h[2])):(r=s-o*h[1])>=0&&(r=s-o*(1-h[1]))<=0&&(r=0),(r*=e.axisExpandWidth/u)?QL(r,n,a,"all"):l="none";else{o=n[1]-n[0];(n=[ik(0,a[1]*s/o-o/2)])[1]=ek(a[1],n[0]+o),n[0]=n[1]-o}return{axisExpandWindow:n,behavior:l}}},Fa.register("parallel",{create:function(t,e){var i=[];return t.eachComponent("parallel",function(n,o){var a=new Nf(n,t,e);a.name="parallel_"+o,a.resize(n,e),n.coordinateSystem=a,a.model=n,i.push(a)}),t.eachSeries(function(e){if("parallel"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"parallel",index:e.get("parallelIndex"),id:e.get("parallelId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}});var sk=lI.extend({type:"baseParallelAxis",axis:null,activeIntervals:[],getAreaSelectStyle:function(){return Qb([["fill","color"],["lineWidth","borderWidth"],["stroke","borderColor"],["width","width"],["opacity","opacity"]])(this.getModel("areaSelectStyle"))},setActiveIntervals:function(t){var e=this.activeIntervals=i(t);if(e)for(var n=e.length-1;n>=0;n--)Fo(e[n])},getActiveState:function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(t))return"inactive";if(1===e.length){var i=e[0];if(i[0]<=t&&t<=i[1])return"active"}else for(var n=0,o=e.length;n5)return;var n=this._model.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]);"none"!==n.behavior&&this._dispatchExpand({axisExpandWindow:n.axisExpandWindow})}this._mouseDownPoint=null},mousemove:function(t){if(!this._mouseDownPoint&&Ip(this,"mousemove")){var e=this._model,i=e.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]),n=i.behavior;"jump"===n&&this._throttledDispatchExpand.debounceNextCall(e.get("axisExpandDebounce")),this._throttledDispatchExpand("none"===n?null:{axisExpandWindow:i.axisExpandWindow,animation:"jump"===n&&null})}}};Ns(function(t){Cf(t),Lf(t)}),YI.extend({type:"series.parallel",dependencies:["parallel"],visualColorAccessPath:"lineStyle.color",getInitialData:function(t,e){var i=this.getSource();return Tp(i,this),ml(i,this)},getRawIndicesByActiveState:function(t){var e=this.coordinateSystem,i=this.getData(),n=[];return e.eachActiveState(i,function(e,o){t===e&&n.push(i.getRawIndex(o))}),n},defaultOption:{zlevel:0,z:2,coordinateSystem:"parallel",parallelIndex:0,label:{show:!1},inactiveOpacity:.05,activeOpacity:1,lineStyle:{width:1,opacity:.45,type:"solid"},emphasis:{label:{show:!1}},progressive:500,smooth:!1,animationEasing:"linear"}});var Dk=.3,Ck=(Ar.extend({type:"parallel",init:function(){this._dataGroup=new tb,this.group.add(this._dataGroup),this._data,this._initialized},render:function(t,e,i,n){var o=this._dataGroup,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.dimensions,u=kp(t);if(a.diff(r).add(function(t){Pp(Lp(a,o,t,l,s),a,t,u)}).update(function(e,i){var o=r.getItemGraphicEl(i),h=Cp(a,e,l,s);a.setItemGraphicEl(e,o),Io(o,{shape:{points:h}},n&&!1===n.animation?null:t,e),Pp(o,a,e,u)}).remove(function(t){var e=r.getItemGraphicEl(t);o.remove(e)}).execute(),!this._initialized){this._initialized=!0;var h=Dp(s,t,function(){setTimeout(function(){o.removeClipPath()})});o.setClipPath(h)}this._data=a},incrementalPrepareRender:function(t,e,i){this._initialized=!0,this._data=null,this._dataGroup.removeAll()},incrementalRender:function(t,e,i){for(var n=e.getData(),o=e.coordinateSystem,a=o.dimensions,r=kp(e),s=t.start;sn&&(n=e)}),d(e,function(e){var o=new hL({type:"color",mappingMethod:"linear",dataExtent:[i,n],visual:t.get("color")}).mapValueToVisual(e.getLayout().value);e.setVisual("color",o);var a=e.getModel().get("itemStyle.color");null!=a&&e.setVisual("color",a)})}})});var Ok={_baseAxisDim:null,getInitialData:function(t,e){var i,n,o=e.getComponent("xAxis",this.get("xAxisIndex")),a=e.getComponent("yAxis",this.get("yAxisIndex")),r=o.get("type"),s=a.get("type");"category"===r?(t.layout="horizontal",i=o.getOrdinalMeta(),n=!0):"category"===s?(t.layout="vertical",i=a.getOrdinalMeta(),n=!0):t.layout=t.layout||"horizontal";var l=["x","y"],u="horizontal"===t.layout?0:1,h=this._baseAxisDim=l[u],c=l[1-u],f=[o,a],p=f[u].get("type"),g=f[1-u].get("type"),m=t.data;if(m&&n){var v=[];d(m,function(t,e){var i;t.value&&y(t.value)?(i=t.value.slice(),t.value.unshift(e)):y(t)?(i=t.slice(),t.unshift(e)):i=t,v.push(i)}),t.data=v}var x=this.defaultValueDimensions;return oC(this,{coordDimensions:[{name:h,type:qs(p),ordinalMeta:i,otherDims:{tooltip:!1,itemName:0},dimsDef:["base"]},{name:c,type:qs(g),dimsDef:x.slice()}],dimensionsCount:x.length+1})},getBaseAxis:function(){var t=this._baseAxisDim;return this.ecModel.getComponent(t+"Axis",this.get(t+"AxisIndex")).axis}};h(YI.extend({type:"series.boxplot",dependencies:["xAxis","yAxis","grid"],defaultValueDimensions:[{name:"min",defaultTooltip:!0},{name:"Q1",defaultTooltip:!0},{name:"median",defaultTooltip:!0},{name:"Q3",defaultTooltip:!0},{name:"max",defaultTooltip:!0}],dimensions:null,defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,layout:null,boxWidth:[7,50],itemStyle:{color:"#fff",borderWidth:1},emphasis:{itemStyle:{borderWidth:2,shadowBlur:5,shadowOffsetX:2,shadowOffsetY:2,shadowColor:"rgba(0,0,0,0.4)"}},animationEasing:"elasticOut",animationDuration:800}}),Ok,!0);var Ek=["itemStyle"],Rk=["emphasis","itemStyle"],zk=(Ar.extend({type:"boxplot",render:function(t,e,i){var n=t.getData(),o=this.group,a=this._data;this._data||o.removeAll();var r="horizontal"===t.get("layout")?1:0;n.diff(a).add(function(t){if(n.hasValue(t)){var e=ig(n.getItemLayout(t),n,t,r,!0);n.setItemGraphicEl(t,e),o.add(e)}}).update(function(t,e){var i=a.getItemGraphicEl(e);if(n.hasValue(t)){var s=n.getItemLayout(t);i?ng(s,i,n,t):i=ig(s,n,t,r),o.add(i),n.setItemGraphicEl(t,i)}else o.remove(i)}).remove(function(t){var e=a.getItemGraphicEl(t);e&&o.remove(e)}).execute(),this._data=n},remove:function(t){var e=this.group,i=this._data;this._data=null,i&&i.eachItemGraphicEl(function(t){t&&e.remove(t)})},dispose:B}),Pn.extend({type:"boxplotBoxPath",shape:{},buildPath:function(t,e){var i=e.points,n=0;for(t.moveTo(i[n][0],i[n][1]),n++;n<4;n++)t.lineTo(i[n][0],i[n][1]);for(t.closePath();n0?jk:Yk)}function n(t,e){return e.get(t>0?Uk:Xk)}var o=t.getData(),a=t.pipelineContext.large;if(o.setVisual({legendSymbol:"roundRect",colorP:i(1,t),colorN:i(-1,t),borderColorP:n(1,t),borderColorN:n(-1,t)}),!e.isSeriesFiltered(t))return!a&&{progress:function(t,e){for(var o;null!=(o=t.next());){var a=e.getItemModel(o),r=e.getItemLayout(o).sign;e.setItemVisual(o,{color:i(r,a),borderColor:n(r,a)})}}}}},Kk="undefined"!=typeof Float32Array?Float32Array:Array,$k={seriesType:"candlestick",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.getData(),n=pg(t,i),o=0,a=1,r=["x","y"],s=i.mapDimension(r[o]),l=i.mapDimension(r[a],!0),u=l[0],h=l[1],c=l[2],d=l[3];if(i.setLayout({candleWidth:n,isSimpleBox:n<=1.3}),!(null==s||l.length<4))return{progress:t.pipelineContext.large?function(t,i){for(var n,r,l=new Kk(5*t.count),f=0,p=[],g=[];null!=(r=t.next());){var m=i.get(s,r),v=i.get(u,r),y=i.get(h,r),x=i.get(c,r),_=i.get(d,r);isNaN(m)||isNaN(x)||isNaN(_)?(l[f++]=NaN,f+=4):(l[f++]=fg(i,r,v,y,h),p[o]=m,p[a]=x,n=e.dataToPoint(p,null,g),l[f++]=n?n[0]:NaN,l[f++]=n?n[1]:NaN,p[a]=_,n=e.dataToPoint(p,null,g),l[f++]=n?n[1]:NaN)}i.setLayout("largePoints",l)}:function(t,i){function r(t,i){var n=[];return n[o]=i,n[a]=t,isNaN(i)||isNaN(t)?[NaN,NaN]:e.dataToPoint(n)}function l(t,e,i){var a=e.slice(),r=e.slice();a[o]=Jn(a[o]+n/2,1,!1),r[o]=Jn(r[o]-n/2,1,!0),i?t.push(a,r):t.push(r,a)}function f(t){return t[o]=Jn(t[o],1),t}for(var p;null!=(p=t.next());){var g=i.get(s,p),m=i.get(u,p),v=i.get(h,p),y=i.get(c,p),x=i.get(d,p),_=Math.min(m,v),w=Math.max(m,v),b=r(_,g),S=r(w,g),M=r(y,g),I=r(x,g),T=[];l(T,S,0),l(T,b,1),T.push(f(I),f(S),f(M),f(b)),i.setItemLayout(p,{sign:fg(i,p,m,v,h),initBaseline:m>v?S[a]:b[a],ends:T,brushRect:function(t,e,i){var s=r(t,i),l=r(e,i);return s[o]-=n/2,l[o]-=n/2,{x:s[0],y:s[1],width:a?n:l[0]-s[0],height:a?l[1]-s[1]:n}}(y,x,g)})}}}}};Ns(function(t){t&&y(t.series)&&d(t.series,function(t){w(t)&&"k"===t.type&&(t.type="candlestick")})}),Bs(qk),zs($k),YI.extend({type:"series.effectScatter",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},brushSelector:"point",defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,effectType:"ripple",progressive:0,showEffectOn:"render",rippleEffect:{period:4,scale:2.5,brushType:"fill"},symbolSize:10}});var Jk=vg.prototype;Jk.stopEffectAnimation=function(){this.childAt(1).removeAll()},Jk.startEffectAnimation=function(t){for(var e=t.symbolType,i=t.color,n=this.childAt(1),o=0;o<3;o++){var a=Jl(e,-1,-1,2,2,i);a.attr({style:{strokeNoScale:!0},z2:99,silent:!0,scale:[.5,.5]});var r=-o/3*t.period+t.effectOffset;a.animate("",!0).when(t.period,{scale:[t.rippleScale/2,t.rippleScale/2]}).delay(r).start(),a.animateStyle(!0).when(t.period,{opacity:0}).delay(r).start(),n.add(a)}mg(n,t)},Jk.updateEffectAnimation=function(t){for(var e=this._effectCfg,i=this.childAt(1),n=["symbolType","period","rippleScale"],o=0;o "))},preventIncremental:function(){return!!this.get("effect.show")},getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,label:{show:!1,position:"end"},lineStyle:{opacity:.5}}}),iP=xg.prototype;iP.createLine=function(t,e,i){return new rf(t,e,i)},iP._updateEffectSymbol=function(t,e){var i=t.getItemModel(e).getModel("effect"),n=i.get("symbolSize"),o=i.get("symbol");y(n)||(n=[n,n]);var a=i.get("color")||t.getItemVisual(e,"color"),r=this.childAt(1);this._symbolType!==o&&(this.remove(r),(r=Jl(o,-.5,-.5,1,1,a)).z2=100,r.culling=!0,this.add(r)),r&&(r.setStyle("shadowColor",a),r.setStyle(i.getItemStyle(["color"])),r.attr("scale",n),r.setColor(a),r.attr("scale",n),this._symbolType=o,this._updateEffectAnimation(t,i,e))},iP._updateEffectAnimation=function(t,e,i){var n=this.childAt(1);if(n){var o=this,a=t.getItemLayout(i),r=1e3*e.get("period"),s=e.get("loop"),l=e.get("constantSpeed"),u=T(e.get("delay"),function(e){return e/t.count()*r/3}),h="function"==typeof u;if(n.ignore=!0,this.updateAnimationPoints(n,a),l>0&&(r=this.getLineLength(n)/l*1e3),r!==this._period||s!==this._loop){n.stopAnimation();var c=u;h&&(c=u(i)),n.__t>0&&(c=-r*n.__t),n.__t=0;var d=n.animate("",s).when(r,{__t:1}).delay(c).during(function(){o.updateSymbolPosition(n)});s||d.done(function(){o.remove(n)}),d.start()}this._period=r,this._loop=s}},iP.getLineLength=function(t){return uw(t.__p1,t.__cp1)+uw(t.__cp1,t.__p2)},iP.updateAnimationPoints=function(t,e){t.__p1=e[0],t.__p2=e[1],t.__cp1=e[2]||[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]},iP.updateData=function(t,e,i){this.childAt(0).updateData(t,e,i),this._updateEffectSymbol(t,e)},iP.updateSymbolPosition=function(t){var e=t.__p1,i=t.__p2,n=t.__cp1,o=t.__t,a=t.position,r=sn,s=ln;a[0]=r(e[0],n[0],i[0],o),a[1]=r(e[1],n[1],i[1],o);var l=s(e[0],n[0],i[0],o),u=s(e[1],n[1],i[1],o);t.rotation=-Math.atan2(u,l)-Math.PI/2,t.ignore=!1},iP.updateLayout=function(t,e){this.childAt(0).updateLayout(t,e);var i=t.getItemModel(e).getModel("effect");this._updateEffectAnimation(t,i,e)},u(xg,tb);var nP=_g.prototype;nP._createPolyline=function(t,e,i){var n=t.getItemLayout(e),o=new gM({shape:{points:n}});this.add(o),this._updateCommonStl(t,e,i)},nP.updateData=function(t,e,i){var n=t.hostModel;Io(this.childAt(0),{shape:{points:t.getItemLayout(e)}},n,e),this._updateCommonStl(t,e,i)},nP._updateCommonStl=function(t,e,i){var n=this.childAt(0),o=t.getItemModel(e),a=t.getItemVisual(e,"color"),s=i&&i.lineStyle,l=i&&i.hoverLineStyle;i&&!t.hasItemOption||(s=o.getModel("lineStyle").getLineStyle(),l=o.getModel("emphasis.lineStyle").getLineStyle()),n.useStyle(r({strokeNoScale:!0,fill:"none",stroke:a},s)),n.hoverStyle=l,fo(this)},nP.updateLayout=function(t,e){this.childAt(0).setShape("points",t.getItemLayout(e))},u(_g,tb);var oP=wg.prototype;oP.createLine=function(t,e,i){return new _g(t,e,i)},oP.updateAnimationPoints=function(t,e){this._points=e;for(var i=[0],n=0,o=1;o=0&&!(n[r]<=e);r--);r=Math.min(r,o-2)}else{for(var r=a;re);r++);r=Math.min(r-1,o-2)}J(t.position,i[r],i[r+1],(e-n[r])/(n[r+1]-n[r]));var s=i[r+1][0]-i[r][0],l=i[r+1][1]-i[r][1];t.rotation=-Math.atan2(l,s)-Math.PI/2,this._lastFrame=r,this._lastFramePercent=e,t.ignore=!1}},u(wg,xg);var aP=Un({shape:{polyline:!1,curveness:0,segs:[]},buildPath:function(t,e){var i=e.segs,n=e.curveness;if(e.polyline)for(r=0;r0){t.moveTo(i[r++],i[r++]);for(var a=1;a0){var c=(s+u)/2-(l-h)*n,d=(l+h)/2-(u-s)*n;t.quadraticCurveTo(c,d,u,h)}else t.lineTo(u,h)}},findDataIndex:function(t,e){var i=this.shape,n=i.segs,o=i.curveness;if(i.polyline)for(var a=0,r=0;r0)for(var l=n[r++],u=n[r++],h=1;h0){if(_n(l,u,(l+c)/2-(u-d)*o,(u+d)/2-(c-l)*o,c,d))return a}else if(yn(l,u,c,d))return a;a++}return-1}}),rP=bg.prototype;rP.isPersistent=function(){return!this._incremental},rP.updateData=function(t){this.group.removeAll();var e=new aP({rectHover:!0,cursor:"default"});e.setShape({segs:t.getLayout("linesPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},rP.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>5e5?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},rP.incrementalUpdate=function(t,e){var i=new aP;i.setShape({segs:e.getLayout("linesPoints")}),this._setCommon(i,e,!!this._incremental),this._incremental?this._incremental.addDisplayable(i,!0):(i.rectHover=!0,i.cursor="default",i.__startIndex=t.start,this.group.add(i))},rP.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},rP._setCommon=function(t,e,i){var n=e.hostModel;t.setShape({polyline:n.get("polyline"),curveness:n.get("lineStyle.curveness")}),t.useStyle(n.getModel("lineStyle").getLineStyle()),t.style.strokeNoScale=!0;var o=e.getVisual("color");o&&t.setStyle("stroke",o),t.setStyle("fill"),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>0&&(t.dataIndex=i+t.__startIndex)}))},rP._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()};var sP={seriesType:"lines",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.get("polyline"),n=t.pipelineContext.large;return{progress:function(o,a){var r=[];if(n){var s,l=o.end-o.start;if(i){for(var u=0,h=o.start;h0){var I=a(v)?s:l;v>0&&(v=v*S+b),x[_++]=I[M],x[_++]=I[M+1],x[_++]=I[M+2],x[_++]=I[M+3]*v*256}else _+=4}return c.putImageData(y,0,0),h},_getBrush:function(){var t=this._brushCanvas||(this._brushCanvas=iw()),e=this.pointSize+this.blurSize,i=2*e;t.width=i,t.height=i;var n=t.getContext("2d");return n.clearRect(0,0,i,i),n.shadowOffsetX=i,n.shadowBlur=this.blurSize,n.shadowColor="#000",n.beginPath(),n.arc(-e,e,this.pointSize,0,2*Math.PI,!0),n.closePath(),n.fill(),t},_getGradient:function(t,e,i){for(var n=this._gradientPixels,o=n[i]||(n[i]=new Uint8ClampedArray(1024)),a=[0,0,0,0],r=0,s=0;s<256;s++)e[i](s/255,!0,a),o[r++]=a[0],o[r++]=a[1],o[r++]=a[2],o[r++]=a[3];return o}},Zs({type:"heatmap",render:function(t,e,i){var n;e.eachComponent("visualMap",function(e){e.eachTargetSeries(function(i){i===t&&(n=e)})}),this.group.removeAll(),this._incrementalDisplayable=null;var o=t.coordinateSystem;"cartesian2d"===o.type||"calendar"===o.type?this._renderOnCartesianAndCalendar(t,i,0,t.getData().count()):Ag(o)&&this._renderOnGeo(o,t,n,i)},incrementalPrepareRender:function(t,e,i){this.group.removeAll()},incrementalRender:function(t,e,i,n){e.coordinateSystem&&this._renderOnCartesianAndCalendar(e,n,t.start,t.end,!0)},_renderOnCartesianAndCalendar:function(t,e,i,n,o){var r,s,l=t.coordinateSystem;if("cartesian2d"===l.type){var u=l.getAxis("x"),h=l.getAxis("y");r=u.getBandWidth(),s=h.getBandWidth()}for(var c=this.group,d=t.getData(),f=t.getModel("itemStyle").getItemStyle(["color"]),p=t.getModel("emphasis.itemStyle").getItemStyle(),g=t.getModel("label"),m=t.getModel("emphasis.label"),v=l.type,y="cartesian2d"===v?[d.mapDimension("x"),d.mapDimension("y"),d.mapDimension("value")]:[d.mapDimension("time"),d.mapDimension("value")],x=i;x=e.y&&t[1]<=e.y+e.height:i.contain(i.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},pointToData:function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},dataToPoint:function(t){var e=this.getAxis(),i=this.getRect(),n=[],o="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=e.toGlobalCoord(e.dataToCoord(+t)),n[1-o]=0===o?i.y+i.height/2:i.x+i.width/2,n}},Fa.register("single",{create:function(t,e){var i=[];return t.eachComponent("singleAxis",function(n,o){var a=new $g(n,t,e);a.name="single_"+o,a.resize(n,e),n.coordinateSystem=a,i.push(a)}),t.eachSeries(function(e){if("singleAxis"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"singleAxis",index:e.get("singleAxisIndex"),id:e.get("singleAxisId")})[0];e.coordinateSystem=i&&i.coordinateSystem}}),i},dimensions:$g.prototype.dimensions});var gP=["axisLine","axisTickLabel","axisName"],mP=XD.extend({type:"singleAxis",axisPointerClass:"SingleAxisPointer",render:function(t,e,i,n){var o=this.group;o.removeAll();var a=Jg(t),r=new FD(t,a);d(gP,r.add,r),o.add(r.getGroup()),t.get("splitLine.show")&&this._splitLine(t),mP.superCall(this,"render",t,e,i,n)},_splitLine:function(t){var e=t.axis;if(!e.scale.isBlank()){var i=t.getModel("splitLine"),n=i.getModel("lineStyle"),o=n.get("width"),a=n.get("color");a=a instanceof Array?a:[a];for(var r=t.coordinateSystem.getRect(),s=e.isHorizontal(),l=[],u=0,h=e.getTicksCoords({tickModel:i}),c=[],d=[],f=0;f=0)&&i({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})})},remove:function(t,e){gm(e.getZr(),"axisPointer"),IP.superApply(this._model,"remove",arguments)},dispose:function(t,e){gm("axisPointer",e),IP.superApply(this._model,"dispose",arguments)}}),TP=Bi(),AP=i,DP=m;(mm.prototype={_group:null,_lastGraphicKey:null,_handle:null,_dragging:!1,_lastValue:null,_lastStatus:null,_payloadInfo:null,animationThreshold:15,render:function(t,e,i,n){var o=e.get("value"),a=e.get("status");if(this._axisModel=t,this._axisPointerModel=e,this._api=i,n||this._lastValue!==o||this._lastStatus!==a){this._lastValue=o,this._lastStatus=a;var r=this._group,s=this._handle;if(!a||"hide"===a)return r&&r.hide(),void(s&&s.hide());r&&r.show(),s&&s.show();var l={};this.makeElOption(l,o,t,e,i);var u=l.graphicKey;u!==this._lastGraphicKey&&this.clear(i),this._lastGraphicKey=u;var h=this._moveAnimation=this.determineAnimation(t,e);if(r){var c=v(vm,e,h);this.updatePointerEl(r,l,c,e),this.updateLabelEl(r,l,c,e)}else r=this._group=new tb,this.createPointerEl(r,l,t,e),this.createLabelEl(r,l,t,e),i.getZr().add(r);wm(r,e,!0),this._renderHandle(o)}},remove:function(t){this.clear(t)},dispose:function(t){this.clear(t)},determineAnimation:function(t,e){var i=e.get("animation"),n=t.axis,o="category"===n.type,a=e.get("snap");if(!a&&!o)return!1;if("auto"===i||null==i){var r=this.animationThreshold;if(o&&n.getBandWidth()>r)return!0;if(a){var s=Mh(t).seriesDataCount,l=n.getExtent();return Math.abs(l[0]-l[1])/s>r}return!1}return!0===i},makeElOption:function(t,e,i,n,o){},createPointerEl:function(t,e,i,n){var o=e.pointer;if(o){var a=TP(t).pointerEl=new zM[o.type](AP(e.pointer));t.add(a)}},createLabelEl:function(t,e,i,n){if(e.label){var o=TP(t).labelEl=new yM(AP(e.label));t.add(o),xm(o,n)}},updatePointerEl:function(t,e,i){var n=TP(t).pointerEl;n&&(n.setStyle(e.pointer.style),i(n,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,i,n){var o=TP(t).labelEl;o&&(o.setStyle(e.label.style),i(o,{shape:e.label.shape,position:e.label.position}),xm(o,n))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e=this._axisPointerModel,i=this._api.getZr(),n=this._handle,o=e.getModel("handle"),a=e.get("status");if(!o.get("show")||!a||"hide"===a)return n&&i.remove(n),void(this._handle=null);var r;this._handle||(r=!0,n=this._handle=Po(o.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){mw(t.event)},onmousedown:DP(this._onHandleDragMove,this,0,0),drift:DP(this._onHandleDragMove,this),ondragend:DP(this._onHandleDragEnd,this)}),i.add(n)),wm(n,e,!1);var s=["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"];n.setStyle(o.getItemStyle(null,s));var l=o.get("size");y(l)||(l=[l,l]),n.attr("scale",[l[0]/2,l[1]/2]),Nr(this,"_doDispatchAxisPointer",o.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,r)}},_moveHandleToValue:function(t,e){vm(this._axisPointerModel,!e&&this._moveAnimation,this._handle,_m(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var i=this._handle;if(i){this._dragging=!0;var n=this.updateHandleTransform(_m(i),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=n,i.stopAnimation(),i.attr(_m(n)),TP(i).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),i=this._group,n=this._handle;e&&i&&(this._lastGraphicKey=null,i&&e.remove(i),n&&e.remove(n),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}}).constructor=mm,ji(mm);var CP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.grid,s=n.get("type"),l=km(r,a).getOtherAxis(a).getGlobalExtent(),u=a.toGlobalCoord(a.dataToCoord(e,!0));if(s&&"none"!==s){var h=bm(n),c=LP[s](a,u,l,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Lh(r.model,i),i,n,o)},getHandleTransform:function(t,e,i){var n=Lh(e.axis.grid.model,e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.grid,r=o.getGlobalExtent(!0),s=km(a,o).getOtherAxis(o).getGlobalExtent(),l="x"===o.dim?0:1,u=t.position;u[l]+=e[l],u[l]=Math.min(r[1],u[l]),u[l]=Math.max(r[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];var d=[{verticalAlign:"middle"},{align:"center"}];return{position:u,rotation:t.rotation,cursorPoint:c,tooltipOption:d[l]}}}),LP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Pm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=Math.max(1,t.getBandWidth()),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Pm(t))}}};XD.registerAxisPointerClass("CartesianAxisPointer",CP),Ns(function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!y(e)&&(t.axisPointer.link=[e])}}),Os(VT.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=vh(t,e)}),Es({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,i){var n=t.currTrigger,o=[t.x,t.y],a=t,r=t.dispatchAction||m(i.dispatchAction,i),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){lm(o)&&(o=xP({seriesIndex:a.seriesIndex,dataIndex:a.dataIndex},e).point);var l=lm(o),u=a.axesInfo,h=s.axesInfo,c="leave"===n||lm(o),d={},f={},p={list:[],map:{}},g={showPointer:wP(em,f),showTooltip:wP(im,p)};_P(s.coordSysMap,function(t,e){var i=l||t.containPoint(o);_P(s.coordSysAxesInfo[e],function(t,e){var n=t.axis,a=rm(u,t);if(!c&&i&&(!u||a)){var r=a&&a.value;null!=r||l||(r=n.pointToData(o)),null!=r&&Qg(t,r,g,!1,d)}})});var v={};return _P(h,function(t,e){var i=t.linkGroup;i&&!f[e]&&_P(i.axesInfo,function(e,n){var o=f[n];if(e!==t&&o){var a=o.value;i.mapper&&(a=t.axis.scale.parse(i.mapper(a,sm(e),sm(t)))),v[t.key]=a}})}),_P(v,function(t,e){Qg(h[e],t,g,!0,d)}),nm(f,h,d),om(p,o,t,r),am(h,0,i),d}});var kP=["x","y"],PP=["width","height"],NP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.coordinateSystem,s=Om(r,1-Nm(a)),l=r.dataToPoint(e)[0],u=n.get("type");if(u&&"none"!==u){var h=bm(n),c=OP[u](a,l,s,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Jg(i),i,n,o)},getHandleTransform:function(t,e,i){var n=Jg(e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.coordinateSystem,r=Nm(o),s=Om(a,r),l=t.position;l[r]+=e[r],l[r]=Math.min(s[1],l[r]),l[r]=Math.max(s[0],l[r]);var u=Om(a,1-r),h=(u[1]+u[0])/2,c=[h,h];return c[r]=l[r],{position:l,rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}}}),OP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Nm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=t.getBandWidth(),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Nm(t))}}};XD.registerAxisPointerClass("SingleAxisPointer",NP),Ws({type:"single"});var EP=YI.extend({type:"series.themeRiver",dependencies:["singleAxis"],nameMap:null,init:function(t){EP.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()}},fixData:function(t){var e=t.length,i=[];Zi(t,function(t){return t[2]}).buckets.each(function(t,e){i.push({name:e,dataList:t})});for(var n=i.length,o=-1,a=-1,r=0;ro&&(o=s,a=r)}for(var l=0;lMath.PI/2?"right":"left"):x&&"center"!==x?"left"===x?(f=u.r0+y,p>Math.PI/2&&(x="right")):"right"===x&&(f=u.r-y,p>Math.PI/2&&(x="left")):(f=(u.r+u.r0)/2,x="center"),d.attr("style",{text:l,textAlign:x,textVerticalAlign:n("verticalAlign")||"middle",opacity:n("opacity")});var _=f*g+u.cx,w=f*m+u.cy;d.attr("position",[_,w]);var b=n("rotate"),S=0;"radial"===b?(S=-p)<-Math.PI/2&&(S+=Math.PI):"tangential"===b?(S=Math.PI/2-p)>Math.PI/2?S-=Math.PI:S<-Math.PI/2&&(S+=Math.PI):"number"==typeof b&&(S=b*Math.PI/180),d.attr("rotation",S)},VP._initEvents=function(t,e,i,n){t.off("mouseover").off("mouseout").off("emphasis").off("normal");var o=this,a=function(){o.onEmphasis(n)},r=function(){o.onNormal()};i.isAnimationEnabled()&&t.on("mouseover",a).on("mouseout",r).on("emphasis",a).on("normal",r).on("downplay",function(){o.onDownplay()}).on("highlight",function(){o.onHighlight()})},u(Vm,tb);Ar.extend({type:"sunburst",init:function(){},render:function(t,e,i,n){function o(i,n){if(c||!i||i.getValue()||(i=null),i!==l&&n!==l)if(n&&n.piece)i?(n.piece.updateData(!1,i,"normal",t,e),s.setItemGraphicEl(i.dataIndex,n.piece)):a(n);else if(i){var o=new Vm(i,t,e);h.add(o),s.setItemGraphicEl(i.dataIndex,o)}}function a(t){t&&t.piece&&(h.remove(t.piece),t.piece=null)}var r=this;this.seriesModel=t,this.api=i,this.ecModel=e;var s=t.getData(),l=s.tree.root,u=t.getViewRoot(),h=this.group,c=t.get("renderLabelForZeroData"),d=[];u.eachNode(function(t){d.push(t)});var f=this._oldChildren||[];if(function(t,e){function i(t){return t.getId()}function n(i,n){o(null==i?null:t[i],null==n?null:e[n])}0===t.length&&0===e.length||new Xs(e,t,i,i).add(n).update(n).remove(v(n,null)).execute()}(d,f),function(i,n){if(n.depth>0){r.virtualPiece?r.virtualPiece.updateData(!1,i,"normal",t,e):(r.virtualPiece=new Vm(i,t,e),h.add(r.virtualPiece)),n.piece._onclickEvent&&n.piece.off("click",n.piece._onclickEvent);var o=function(t){r._rootToNode(n.parentNode)};n.piece._onclickEvent=o,r.virtualPiece.on("click",o)}else r.virtualPiece&&(h.remove(r.virtualPiece),r.virtualPiece=null)}(l,u),n&&n.highlight&&n.highlight.piece){var p=t.getShallow("highlightPolicy");n.highlight.piece.onEmphasis(p)}else if(n&&n.unhighlight){var g=this.virtualPiece;!g&&l.children.length&&(g=l.children[0].piece),g&&g.onNormal()}this._initEvents(),this._oldChildren=d},dispose:function(){},_initEvents:function(){var t=this,e=function(e){var i=!1;t.seriesModel.getViewRoot().eachNode(function(n){if(!i&&n.piece&&n.piece.childAt(0)===e.target){var o=n.getModel().get("nodeClick");if("rootToNode"===o)t._rootToNode(n);else if("link"===o){var a=n.getModel(),r=a.get("link");if(r){var s=a.get("target",!0)||"_blank";window.open(r,s)}}i=!0}})};this.group._onclickEvent&&this.group.off("click",this.group._onclickEvent),this.group.on("click",e),this.group._onclickEvent=e},_rootToNode:function(t){t!==this.seriesModel.getViewRoot()&&this.api.dispatchAction({type:"sunburstRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t})},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var GP="sunburstRootToNode";Es({type:GP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[GP],e);if(n){var o=e.getViewRoot();o&&(t.direction=hd(o,n.node)?"rollUp":"drillDown"),e.resetViewRoot(n.node)}})});var FP="sunburstHighlight";Es({type:FP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[FP],e);n&&(t.highlight=n.node)})});Es({type:"sunburstUnhighlight",update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){t.unhighlight=!0})});var WP=Math.PI/180;Bs(v(uC,"sunburst")),zs(v(function(t,e,i,n){e.eachSeriesByType(t,function(t){var e=t.get("center"),n=t.get("radius");y(n)||(n=[0,n]),y(e)||(e=[e,e]);var o=i.getWidth(),a=i.getHeight(),r=Math.min(o,a),s=Vo(e[0],o),l=Vo(e[1],a),u=Vo(n[0],r/2),h=Vo(n[1],r/2),c=-t.get("startAngle")*WP,f=t.get("minAngle")*WP,p=t.getData().tree.root,g=t.getViewRoot(),m=g.depth,v=t.get("sort");null!=v&&Zm(g,v);var x=0;d(g.children,function(t){!isNaN(t.getValue())&&x++});var _=g.getValue(),w=Math.PI/(_||x)*2,b=g.depth>0,S=g.height-(b?-1:1),M=(h-u)/(S||1),I=t.get("clockwise"),T=t.get("stillShowZeroSum"),A=I?1:-1,D=function(t,e){if(t){var i=e;if(t!==p){var n=t.getValue(),o=0===_&&T?w:n*w;on[1]&&n.reverse(),{coordSys:{type:"polar",cx:t.cx,cy:t.cy,r:n[1],r0:n[0]},api:{coord:m(function(n){var o=e.dataToRadius(n[0]),a=i.dataToAngle(n[1]),r=t.coordToPoint([o,a]);return r.push(o,a*Math.PI/180),r}),size:m(qm,t)}}},calendar:function(t){var e=t.getRect(),i=t.getRangeInfo();return{coordSys:{type:"calendar",x:e.x,y:e.y,width:e.width,height:e.height,cellWidth:t.getCellWidth(),cellHeight:t.getCellHeight(),rangeInfo:{start:i.start,end:i.end,weeks:i.weeks,dayCount:i.allDay}},api:{coord:function(e,i){return t.dataToPoint(e,i)}}}}};YI.extend({type:"series.custom",dependencies:["grid","polar","geo","singleAxis","calendar"],defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,useTransform:!0},getInitialData:function(t,e){return ml(this.getSource(),this)},getDataParams:function(t,e,i){var n=YI.prototype.getDataParams.apply(this,arguments);return i&&(n.info=i.info),n}}),Ar.extend({type:"custom",_data:null,render:function(t,e,i,n){var o=this._data,a=t.getData(),r=this.group,s=Qm(t,a,e,i);a.diff(o).add(function(e){ev(null,e,s(e,n),t,r,a)}).update(function(e,i){ev(o.getItemGraphicEl(i),e,s(e,n),t,r,a)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&r.remove(e)}).execute(),this._data=a},incrementalPrepareRender:function(t,e,i){this.group.removeAll(),this._data=null},incrementalRender:function(t,e,i,n,o){for(var a=e.getData(),r=Qm(e,a,i,n),s=t.start;s=0;l--)null==o[l]?o.splice(l,1):delete o[l].$action},_flatten:function(t,e,i){d(t,function(t){if(t){i&&(t.parentOption=i),e.push(t);var n=t.children;"group"===t.type&&n&&this._flatten(n,e,t),delete t.children}},this)},useElOptionsToUpdate:function(){var t=this._elOptionsToUpdate;return this._elOptionsToUpdate=null,t}});Ws({type:"graphic",init:function(t,e){this._elMap=R(),this._lastGraphicModel},render:function(t,e,i){t!==this._lastGraphicModel&&this._clear(),this._lastGraphicModel=t,this._updateElements(t),this._relocate(t,i)},_updateElements:function(t){var e=t.useElOptionsToUpdate();if(e){var i=this._elMap,n=this.group;d(e,function(e){var o=e.$action,a=e.id,r=i.get(a),s=e.parentId,l=null!=s?i.get(s):n,u=e.style;"text"===e.type&&u&&(e.hv&&e.hv[1]&&(u.textVerticalAlign=u.textBaseline=null),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke));var h=fv(e);o&&"merge"!==o?"replace"===o?(dv(r,i),cv(a,l,h,i)):"remove"===o&&dv(r,i):r?r.attr(h):cv(a,l,h,i);var c=i.get(a);c&&(c.__ecGraphicWidth=e.width,c.__ecGraphicHeight=e.height,yv(c,t))})}},_relocate:function(t,e){for(var i=t.option.elements,n=this.group,o=this._elMap,a=i.length-1;a>=0;a--){var r=i[a],s=o.get(r.id);if(s){var l=s.parent;da(s,r,l===n?{width:e.getWidth(),height:e.getHeight()}:{width:l.__ecGraphicWidth||0,height:l.__ecGraphicHeight||0},null,{hv:r.hv,boundingMode:r.bounding})}}},_clear:function(){var t=this._elMap;t.each(function(e){dv(e,t)}),this._elMap=R()},dispose:function(){this._clear()}});var KP=Fs({type:"legend.plain",dependencies:["series"],layoutMode:{type:"box",ignoreSize:!0},init:function(t,e,i){this.mergeDefaultAndTheme(t,i),t.selected=t.selected||{}},mergeOption:function(t){KP.superCall(this,"mergeOption",t)},optionUpdated:function(){this._updateData(this.ecModel);var t=this._data;if(t[0]&&"single"===this.get("selectedMode")){for(var e=!1,i=0;i=0},defaultOption:{zlevel:0,z:4,show:!0,orient:"horizontal",left:"center",top:0,align:"auto",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemGap:10,itemWidth:25,itemHeight:14,inactiveColor:"#ccc",textStyle:{color:"#333"},selectedMode:!0,tooltip:{show:!1}}});Es("legendToggleSelect","legendselectchanged",v(xv,"toggleSelected")),Es("legendSelect","legendselected",v(xv,"select")),Es("legendUnSelect","legendunselected",v(xv,"unSelect"));var $P=v,JP=d,QP=tb,tN=Ws({type:"legend.plain",newlineDisabled:!1,init:function(){this.group.add(this._contentGroup=new QP),this._backgroundEl,this._isFirstRender=!0},getContentGroup:function(){return this._contentGroup},render:function(t,e,i){var n=this._isFirstRender;if(this._isFirstRender=!1,this.resetInner(),t.get("show",!0)){var o=t.get("align");o&&"auto"!==o||(o="right"===t.get("left")&&"vertical"===t.get("orient")?"right":"left"),this.renderInner(o,t,e,i);var a=t.getBoxLayoutParams(),s={width:i.getWidth(),height:i.getHeight()},l=t.get("padding"),u=ca(a,s,l),h=this.layoutInner(t,o,u,n),c=ca(r({width:h.width,height:h.height},a),s,l);this.group.attr("position",[c.x-h.x,c.y-h.y]),this.group.add(this._backgroundEl=wv(h,t))}},resetInner:function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl)},renderInner:function(t,e,i,n){var o=this.getContentGroup(),a=R(),r=e.get("selectedMode"),s=[];i.eachRawSeries(function(t){!t.get("legendHoverLink")&&s.push(t.id)}),JP(e.getData(),function(l,u){var h=l.get("name");if(this.newlineDisabled||""!==h&&"\n"!==h){var c=i.getSeriesByName(h)[0];if(!a.get(h))if(c){var d=c.getData(),f=d.getVisual("color");"function"==typeof f&&(f=f(c.getDataParams(0)));var p=d.getVisual("legendSymbol")||"roundRect",g=d.getVisual("symbol");this._createItem(h,u,l,e,p,g,t,f,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,c.name,null,n,s)).on("mouseout",$P(Mv,c.name,null,n,s)),a.set(h,!0)}else i.eachRawSeries(function(i){if(!a.get(h)&&i.legendDataProvider){var o=i.legendDataProvider(),c=o.indexOfName(h);if(c<0)return;var d=o.getItemVisual(c,"color");this._createItem(h,u,l,e,"roundRect",null,t,d,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,null,h,n,s)).on("mouseout",$P(Mv,null,h,n,s)),a.set(h,!0)}},this)}else o.add(new QP({newline:!0}))},this)},_createItem:function(t,e,i,n,o,r,s,l,u){var h=n.get("itemWidth"),c=n.get("itemHeight"),d=n.get("inactiveColor"),f=n.get("symbolKeepAspect"),p=n.isSelected(t),g=new QP,m=i.getModel("textStyle"),v=i.get("icon"),y=i.getModel("tooltip"),x=y.parentModel;if(o=v||o,g.add(Jl(o,0,0,h,c,p?l:d,null==f||f)),!v&&r&&(r!==o||"none"===r)){var _=.8*c;"none"===r&&(r="circle"),g.add(Jl(r,(h-_)/2,(c-_)/2,_,_,p?l:d,null==f||f))}var w="left"===s?h+5:-5,b=s,S=n.get("formatter"),M=t;"string"==typeof S&&S?M=S.replace("{name}",null!=t?t:""):"function"==typeof S&&(M=S(t)),g.add(new rM({style:mo({},m,{text:M,x:w,y:c/2,textFill:p?m.getTextColor():d,textAlign:b,textVerticalAlign:"middle"})}));var I=new yM({shape:g.getBoundingRect(),invisible:!0,tooltip:y.get("show")?a({content:t,formatter:x.get("formatter",!0)||function(){return t},formatterParams:{componentType:"legend",legendIndex:n.componentIndex,name:t,$vars:["name"]}},y.option):null});return g.add(I),g.eachChild(function(t){t.silent=!0}),I.silent=!u,this.getContentGroup().add(g),fo(g),g.__legendDataIndex=e,g},layoutInner:function(t,e,i){var n=this.getContentGroup();aI(t.get("orient"),n,t.get("itemGap"),i.width,i.height);var o=n.getBoundingRect();return n.attr("position",[-o.x,-o.y]),this.group.getBoundingRect()},remove:function(){this.getContentGroup().removeAll(),this._isFirstRender=!0}});Os(function(t){var e=t.findComponents({mainType:"legend"});e&&e.length&&t.filterSeries(function(t){for(var i=0;ii[l],p=[-c.x,-c.y];n||(p[s]=o.position[s]);var g=[0,0],m=[-d.x,-d.y],v=A(t.get("pageButtonGap",!0),t.get("itemGap",!0));f&&("end"===t.get("pageButtonPosition",!0)?m[s]+=i[l]-d[l]:g[s]+=d[l]+v),m[1-s]+=c[u]/2-d[u]/2,o.attr("position",p),a.attr("position",g),r.attr("position",m);var y=this.group.getBoundingRect();if((y={x:0,y:0})[l]=f?i[l]:c[l],y[u]=Math.max(c[u],d[u]),y[h]=Math.min(0,d[h]+m[1-s]),a.__rectSize=i[l],f){var x={x:0,y:0};x[l]=Math.max(i[l]-d[l]-v,0),x[u]=y[u],a.setClipPath(new yM({shape:x})),a.__rectSize=x[l]}else r.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var _=this._getPageInfo(t);return null!=_.pageIndex&&Io(o,{position:_.contentPosition},!!f&&t),this._updatePageInfoView(t,_),y},_pageGo:function(t,e,i){var n=this._getPageInfo(e)[t];null!=n&&i.dispatchAction({type:"legendScroll",scrollDataIndex:n,legendId:e.id})},_updatePageInfoView:function(t,e){var i=this._controllerGroup;d(["pagePrev","pageNext"],function(n){var o=null!=e[n+"DataIndex"],a=i.childOfName(n);a&&(a.setStyle("fill",o?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),a.cursor=o?"pointer":"default")});var n=i.childOfName("pageText"),o=t.get("pageFormatter"),a=e.pageIndex,r=null!=a?a+1:0,s=e.pageCount;n&&o&&n.setStyle("text",_(o)?o.replace("{current}",r).replace("{total}",s):o({current:r,total:s}))},_getPageInfo:function(t){function e(t){if(t){var e=t.getBoundingRect(),i=e[l]+t.position[r];return{s:i,e:i+e[s],i:t.__legendDataIndex}}}function i(t,e){return t.e>=e&&t.s<=e+a}var n=t.get("scrollDataIndex",!0),o=this.getContentGroup(),a=this._containerGroup.__rectSize,r=t.getOrient().index,s=nN[r],l=oN[r],u=this._findTargetItemIndex(n),h=o.children(),c=h[u],d=h.length,f=d?1:0,p={contentPosition:o.position.slice(),pageCount:f,pageIndex:f-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!c)return p;var g=e(c);p.contentPosition[r]=-g.s;for(var m=u+1,v=g,y=g,x=null;m<=d;++m)(!(x=e(h[m]))&&y.e>v.s+a||x&&!i(x,v.s))&&(v=y.i>v.i?y:x)&&(null==p.pageNextDataIndex&&(p.pageNextDataIndex=v.i),++p.pageCount),y=x;for(var m=u-1,v=g,y=g,x=null;m>=-1;--m)(x=e(h[m]))&&i(y,x.s)||!(v.i=0;){var r=o.indexOf("|}"),s=o.substr(a+"{marker".length,r-a-"{marker".length);s.indexOf("sub")>-1?n["marker"+s]={textWidth:4,textHeight:4,textBorderRadius:2,textBackgroundColor:e[s],textOffset:[3,0]}:n["marker"+s]={textWidth:10,textHeight:10,textBorderRadius:5,textBackgroundColor:e[s]},a=(o=o.substr(r+1)).indexOf("{marker")}this.el=new rM({style:{rich:n,text:t,textLineHeight:20,textBackgroundColor:i.get("backgroundColor"),textBorderRadius:i.get("borderRadius"),textFill:i.get("textStyle.color"),textPadding:i.get("padding")},z:i.get("z")}),this._zr.add(this.el);var l=this;this.el.on("mouseover",function(){l._enterable&&(clearTimeout(l._hideTimeout),l._show=!0),l._inContent=!0}),this.el.on("mouseout",function(){l._enterable&&l._show&&l.hideLater(l._hideDelay),l._inContent=!1})},setEnterable:function(t){this._enterable=t},getSize:function(){var t=this.el.getBoundingRect();return[t.width,t.height]},moveTo:function(t,e){this.el&&this.el.attr("position",[t,e])},hide:function(){this.el?this.el.hide():true,this._show=!1},hideLater:function(t){!this._show||this._inContent&&this._enterable||(t?(this._hideDelay=t,this._show=!1,this._hideTimeout=setTimeout(m(this.hide,this),t)):this.hide())},isShow:function(){return this._show},getOuterSize:function(){return this.getSize()}};var uN=m,hN=d,cN=Vo,dN=new yM({shape:{x:-1,y:-1,width:2,height:2}});Ws({type:"tooltip",init:function(t,e){if(!U_.node){var i=t.getComponent("tooltip").get("renderMode");this._renderMode=Hi(i);var n;"html"===this._renderMode?(n=new Cv(e.getDom(),e),this._newLine="
"):(n=new Lv(e),this._newLine="\n"),this._tooltipContent=n}},render:function(t,e,i){if(!U_.node){this.group.removeAll(),this._tooltipModel=t,this._ecModel=e,this._api=i,this._lastDataByCoordSys=null,this._alwaysShowContent=t.get("alwaysShowContent");var n=this._tooltipContent;n.update(),n.setEnterable(t.get("enterable")),this._initGlobalListener(),this._keepShow()}},_initGlobalListener:function(){var t=this._tooltipModel.get("triggerOn");um("itemTooltip",this._api,uN(function(e,i,n){"none"!==t&&(t.indexOf(e)>=0?this._tryShow(i,n):"leave"===e&&this._hide(n))},this))},_keepShow:function(){var t=this._tooltipModel,e=this._ecModel,i=this._api;if(null!=this._lastX&&null!=this._lastY&&"none"!==t.get("triggerOn")){var n=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout(function(){n.manuallyShowTip(t,e,i,{x:n._lastX,y:n._lastY})})}},manuallyShowTip:function(t,e,i,n){if(n.from!==this.uid&&!U_.node){var o=Pv(n,i);this._ticket="";var a=n.dataByCoordSys;if(n.tooltip&&null!=n.x&&null!=n.y){var r=dN;r.position=[n.x,n.y],r.update(),r.tooltip=n.tooltip,this._tryShow({offsetX:n.x,offsetY:n.y,target:r},o)}else if(a)this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,event:{},dataByCoordSys:n.dataByCoordSys,tooltipOption:n.tooltipOption},o);else if(null!=n.seriesIndex){if(this._manuallyAxisShowTip(t,e,i,n))return;var s=xP(n,e),l=s.point[0],u=s.point[1];null!=l&&null!=u&&this._tryShow({offsetX:l,offsetY:u,position:n.position,target:s.el,event:{}},o)}else null!=n.x&&null!=n.y&&(i.dispatchAction({type:"updateAxisPointer",x:n.x,y:n.y}),this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,target:i.getZr().findHover(n.x,n.y).target,event:{}},o))}},manuallyHideTip:function(t,e,i,n){var o=this._tooltipContent;!this._alwaysShowContent&&this._tooltipModel&&o.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=null,n.from!==this.uid&&this._hide(Pv(n,i))},_manuallyAxisShowTip:function(t,e,i,n){var o=n.seriesIndex,a=n.dataIndex,r=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=o&&null!=a&&null!=r){var s=e.getSeriesByIndex(o);if(s&&"axis"===(t=kv([s.getData().getItemModel(a),s,(s.coordinateSystem||{}).model,t])).get("trigger"))return i.dispatchAction({type:"updateAxisPointer",seriesIndex:o,dataIndex:a,position:n.position}),!0}},_tryShow:function(t,e){var i=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var n=t.dataByCoordSys;n&&n.length?this._showAxisTooltip(n,t):i&&null!=i.dataIndex?(this._lastDataByCoordSys=null,this._showSeriesItemTooltip(t,i,e)):i&&i.tooltip?(this._lastDataByCoordSys=null,this._showComponentItemTooltip(t,i,e)):(this._lastDataByCoordSys=null,this._hide(e))}},_showOrMove:function(t,e){var i=t.get("showDelay");e=m(e,this),clearTimeout(this._showTimout),i>0?this._showTimout=setTimeout(e,i):e()},_showAxisTooltip:function(t,e){var i=this._ecModel,o=this._tooltipModel,a=[e.offsetX,e.offsetY],r=[],s=[],l=kv([e.tooltipOption,o]),u=this._renderMode,h=this._newLine,c={};hN(t,function(t){hN(t.dataByAxis,function(t){var e=i.getComponent(t.axisDim+"Axis",t.axisIndex),o=t.value,a=[];if(e&&null!=o){var l=Im(o,e.axis,i,t.seriesDataIndices,t.valueLabelOpt);d(t.seriesDataIndices,function(r){var h=i.getSeriesByIndex(r.seriesIndex),d=r.dataIndexInside,f=h&&h.getDataParams(d);if(f.axisDim=t.axisDim,f.axisIndex=t.axisIndex,f.axisType=t.axisType,f.axisId=t.axisId,f.axisValue=Xl(e.axis,o),f.axisValueLabel=l,f){s.push(f);var p,g=h.formatTooltip(d,!0,null,u);if(w(g)){p=g.html;var m=g.markers;n(c,m)}else p=g;a.push(p)}});var f=l;"html"!==u?r.push(a.join(h)):r.push((f?ia(f)+h:"")+a.join(h))}})},this),r.reverse(),r=r.join(this._newLine+this._newLine);var f=e.position;this._showOrMove(l,function(){this._updateContentNotChangedOnAxis(t)?this._updatePosition(l,f,a[0],a[1],this._tooltipContent,s):this._showTooltipContent(l,r,s,Math.random(),a[0],a[1],f,void 0,c)})},_showSeriesItemTooltip:function(t,e,i){var n=this._ecModel,o=e.seriesIndex,a=n.getSeriesByIndex(o),r=e.dataModel||a,s=e.dataIndex,l=e.dataType,u=r.getData(),h=kv([u.getItemModel(s),r,a&&(a.coordinateSystem||{}).model,this._tooltipModel]),c=h.get("trigger");if(null==c||"item"===c){var d,f,p=r.getDataParams(s,l),g=r.formatTooltip(s,!1,l,this._renderMode);w(g)?(d=g.html,f=g.markers):(d=g,f=null);var m="item_"+r.name+"_"+s;this._showOrMove(h,function(){this._showTooltipContent(h,d,p,m,t.offsetX,t.offsetY,t.position,t.target,f)}),i({type:"showTip",dataIndexInside:s,dataIndex:u.getRawIndex(s),seriesIndex:o,from:this.uid})}},_showComponentItemTooltip:function(t,e,i){var n=e.tooltip;if("string"==typeof n){var o=n;n={content:o,formatter:o}}var a=new No(n,this._tooltipModel,this._ecModel),r=a.get("content"),s=Math.random();this._showOrMove(a,function(){this._showTooltipContent(a,r,a.get("formatterParams")||{},s,t.offsetX,t.offsetY,t.position,e)}),i({type:"showTip",from:this.uid})},_showTooltipContent:function(t,e,i,n,o,a,r,s,l){if(this._ticket="",t.get("showContent")&&t.get("show")){var u=this._tooltipContent,h=t.get("formatter");r=r||t.get("position");var c=e;if(h&&"string"==typeof h)c=na(h,i,!0);else if("function"==typeof h){var d=uN(function(e,n){e===this._ticket&&(u.setContent(n,l,t),this._updatePosition(t,r,o,a,u,i,s))},this);this._ticket=n,c=h(i,n,d)}u.setContent(c,l,t),u.show(t),this._updatePosition(t,r,o,a,u,i,s)}},_updatePosition:function(t,e,i,n,o,a,r){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var u=o.getSize(),h=t.get("align"),c=t.get("verticalAlign"),d=r&&r.getBoundingRect().clone();if(r&&d.applyTransform(r.transform),"function"==typeof e&&(e=e([i,n],a,o.el,d,{viewSize:[s,l],contentSize:u.slice()})),y(e))i=cN(e[0],s),n=cN(e[1],l);else if(w(e)){e.width=u[0],e.height=u[1];var f=ca(e,{width:s,height:l});i=f.x,n=f.y,h=null,c=null}else"string"==typeof e&&r?(i=(p=Ev(e,d,u))[0],n=p[1]):(i=(p=Nv(i,n,o,s,l,h?null:20,c?null:20))[0],n=p[1]);if(h&&(i-=Rv(h)?u[0]/2:"right"===h?u[0]:0),c&&(n-=Rv(c)?u[1]/2:"bottom"===c?u[1]:0),t.get("confine")){var p=Ov(i,n,o,s,l);i=p[0],n=p[1]}o.moveTo(i,n)},_updateContentNotChangedOnAxis:function(t){var e=this._lastDataByCoordSys,i=!!e&&e.length===t.length;return i&&hN(e,function(e,n){var o=e.dataByAxis||{},a=(t[n]||{}).dataByAxis||[];(i&=o.length===a.length)&&hN(o,function(t,e){var n=a[e]||{},o=t.seriesDataIndices||[],r=n.seriesDataIndices||[];(i&=t.value===n.value&&t.axisType===n.axisType&&t.axisId===n.axisId&&o.length===r.length)&&hN(o,function(t,e){var n=r[e];i&=t.seriesIndex===n.seriesIndex&&t.dataIndex===n.dataIndex})})}),this._lastDataByCoordSys=t,!!i},_hide:function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},dispose:function(t,e){U_.node||(this._tooltipContent.hide(),gm("itemTooltip",e))}}),Es({type:"showTip",event:"showTip",update:"tooltip:manuallyShowTip"},function(){}),Es({type:"hideTip",event:"hideTip",update:"tooltip:manuallyHideTip"},function(){}),Gv.prototype={constructor:Gv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToRadius:aD.prototype.dataToCoord,radiusToData:aD.prototype.coordToData},u(Gv,aD);var fN=Bi();Fv.prototype={constructor:Fv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToAngle:aD.prototype.dataToCoord,angleToData:aD.prototype.coordToData,calculateCategoryInterval:function(){var t=this,e=t.getLabelModel(),i=t.scale,n=i.getExtent(),o=i.count();if(n[1]-n[0]<1)return 0;var a=n[0],r=t.dataToCoord(a+1)-t.dataToCoord(a),s=Math.abs(r),l=ke(a,e.getFont(),"center","top"),u=Math.max(l.height,7)/s;isNaN(u)&&(u=1/0);var h=Math.max(0,Math.floor(u)),c=fN(t.model),d=c.lastAutoInterval,f=c.lastTickCount;return null!=d&&null!=f&&Math.abs(d-h)<=1&&Math.abs(f-o)<=1&&d>h?h=d:(c.lastTickCount=o,c.lastAutoInterval=h),h}},u(Fv,aD);var pN=function(t){this.name=t||"",this.cx=0,this.cy=0,this._radiusAxis=new Gv,this._angleAxis=new Fv,this._radiusAxis.polar=this._angleAxis.polar=this};pN.prototype={type:"polar",axisPointerEnabled:!0,constructor:pN,dimensions:["radius","angle"],model:null,containPoint:function(t){var e=this.pointToCoord(t);return this._radiusAxis.contain(e[0])&&this._angleAxis.contain(e[1])},containData:function(t){return this._radiusAxis.containData(t[0])&&this._angleAxis.containData(t[1])},getAxis:function(t){return this["_"+t+"Axis"]},getAxes:function(){return[this._radiusAxis,this._angleAxis]},getAxesByScale:function(t){var e=[],i=this._angleAxis,n=this._radiusAxis;return i.scale.type===t&&e.push(i),n.scale.type===t&&e.push(n),e},getAngleAxis:function(){return this._angleAxis},getRadiusAxis:function(){return this._radiusAxis},getOtherAxis:function(t){var e=this._angleAxis;return t===e?this._radiusAxis:e},getBaseAxis:function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAngleAxis()},getTooltipAxes:function(t){var e=null!=t&&"auto"!==t?this.getAxis(t):this.getBaseAxis();return{baseAxes:[e],otherAxes:[this.getOtherAxis(e)]}},dataToPoint:function(t,e){return this.coordToPoint([this._radiusAxis.dataToRadius(t[0],e),this._angleAxis.dataToAngle(t[1],e)])},pointToData:function(t,e){var i=this.pointToCoord(t);return[this._radiusAxis.radiusToData(i[0],e),this._angleAxis.angleToData(i[1],e)]},pointToCoord:function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=this.getAngleAxis(),o=n.getExtent(),a=Math.min(o[0],o[1]),r=Math.max(o[0],o[1]);n.inverse?a=r-360:r=a+360;var s=Math.sqrt(e*e+i*i);e/=s,i/=s;for(var l=Math.atan2(-i,e)/Math.PI*180,u=lr;)l+=360*u;return[s,l]},coordToPoint:function(t){var e=t[0],i=t[1]/180*Math.PI;return[Math.cos(i)*e+this.cx,-Math.sin(i)*e+this.cy]}};var gN=lI.extend({type:"polarAxis",axis:null,getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"polar",index:this.option.polarIndex,id:this.option.polarId})[0]}});n(gN.prototype,UA);var mN={angle:{startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:!1}},radius:{splitNumber:5}};ED("angle",gN,Wv,mN.angle),ED("radius",gN,Wv,mN.radius),Fs({type:"polar",dependencies:["polarAxis","angleAxis"],coordinateSystem:null,findAxisModel:function(t){var e;return this.ecModel.eachComponent(t,function(t){t.getCoordSysModel()===this&&(e=t)},this),e},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"80%"}});var vN={dimensions:pN.prototype.dimensions,create:function(t,e){var i=[];return t.eachComponent("polar",function(t,n){var o=new pN(n);o.update=Zv;var a=o.getRadiusAxis(),r=o.getAngleAxis(),s=t.findAxisModel("radiusAxis"),l=t.findAxisModel("angleAxis");Uv(a,s),Uv(r,l),Hv(o,t,e),i.push(o),t.coordinateSystem=o,o.model=t}),t.eachSeries(function(e){if("polar"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"polar",index:e.get("polarIndex"),id:e.get("polarId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}};Fa.register("polar",vN);var yN=["axisLine","axisLabel","axisTick","splitLine","splitArea"];XD.extend({type:"angleAxis",axisPointerClass:"PolarAxisPointer",render:function(t,e){if(this.group.removeAll(),t.get("show")){var n=t.axis,o=n.polar,a=o.getRadiusAxis().getExtent(),r=n.getTicksCoords(),s=f(n.getViewLabels(),function(t){return(t=i(t)).coord=n.dataToCoord(t.tickValue),t});Yv(s),Yv(r),d(yN,function(e){!t.get(e+".show")||n.scale.isBlank()&&"axisLine"!==e||this["_"+e](t,o,r,a,s)},this)}},_axisLine:function(t,e,i,n){var o=t.getModel("axisLine.lineStyle"),a=new sM({shape:{cx:e.cx,cy:e.cy,r:n[jv(e)]},style:o.getLineStyle(),z2:1,silent:!0});a.style.fill=null,this.group.add(a)},_axisTick:function(t,e,i,n){var o=t.getModel("axisTick"),a=(o.get("inside")?-1:1)*o.get("length"),s=n[jv(e)],l=f(i,function(t){return new _M({shape:Xv(e,[s,s+a],t.coord)})});this.group.add(OM(l,{style:r(o.getModel("lineStyle").getLineStyle(),{stroke:t.get("axisLine.lineStyle.color")})}))},_axisLabel:function(t,e,i,n,o){var a=t.getCategories(!0),r=t.getModel("axisLabel"),s=r.get("margin");d(o,function(i,o){var l=r,u=i.tickValue,h=n[jv(e)],c=e.coordToPoint([h+s,i.coord]),d=e.cx,f=e.cy,p=Math.abs(c[0]-d)/h<.3?"center":c[0]>d?"left":"right",g=Math.abs(c[1]-f)/h<.3?"middle":c[1]>f?"top":"bottom";a&&a[u]&&a[u].textStyle&&(l=new No(a[u].textStyle,r,r.ecModel));var m=new rM({silent:!0});this.group.add(m),mo(m.style,l,{x:c[0],y:c[1],textFill:l.getTextColor()||t.get("axisLine.lineStyle.color"),text:i.formattedLabel,textAlign:p,textVerticalAlign:g})},this)},_splitLine:function(t,e,i,n){var o=t.getModel("splitLine").getModel("lineStyle"),a=o.get("color"),s=0;a=a instanceof Array?a:[a];for(var l=[],u=0;u=0?"p":"n",M=y;v&&(n[r][b]||(n[r][b]={p:y,n:y}),M=n[r][b][S]);var I,T,A,D;if("radius"===h.dim){var C=h.dataToRadius(w)-y,L=a.dataToAngle(b);Math.abs(C)=0},kN.findTargetInfo=function(t,e){for(var i=this._targetInfoList,n=dy(e,t),o=0;o=0||AN(n,t.getAxis("y").model)>=0)&&a.push(t)}),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:a[0],coordSyses:a,getPanelRect:ON.grid,xAxisDeclared:r[t.id],yAxisDeclared:s[t.id]})}))},geo:function(t,e){TN(t.geoModels,function(t){var i=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:i,coordSyses:[i],getPanelRect:ON.geo})})}},NN=[function(t,e){var i=t.xAxisModel,n=t.yAxisModel,o=t.gridModel;return!o&&i&&(o=i.axis.grid.model),!o&&n&&(o=n.axis.grid.model),o&&o===e.gridModel},function(t,e){var i=t.geoModel;return i&&i===e.geoModel}],ON={grid:function(){return this.coordSys.grid.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(Ao(t)),e}},EN={lineX:DN(fy,0),lineY:DN(fy,1),rect:function(t,e,i){var n=e[CN[t]]([i[0][0],i[1][0]]),o=e[CN[t]]([i[0][1],i[1][1]]),a=[cy([n[0],o[0]]),cy([n[1],o[1]])];return{values:a,xyMinMax:a}},polygon:function(t,e,i){var n=[[1/0,-1/0],[1/0,-1/0]];return{values:f(i,function(i){var o=e[CN[t]](i);return n[0][0]=Math.min(n[0][0],o[0]),n[1][0]=Math.min(n[1][0],o[1]),n[0][1]=Math.max(n[0][1],o[0]),n[1][1]=Math.max(n[1][1],o[1]),o}),xyMinMax:n}}},RN={lineX:DN(py,0),lineY:DN(py,1),rect:function(t,e,i){return[[t[0][0]-i[0]*e[0][0],t[0][1]-i[0]*e[0][1]],[t[1][0]-i[1]*e[1][0],t[1][1]-i[1]*e[1][1]]]},polygon:function(t,e,i){return f(t,function(t,n){return[t[0]-i[0]*e[n][0],t[1]-i[1]*e[n][1]]})}},zN=["inBrush","outOfBrush"],BN="__ecBrushSelect",VN="__ecInBrushSelectEvent",GN=VT.VISUAL.BRUSH;zs(GN,function(t,e,i){t.eachComponent({mainType:"brush"},function(e){i&&"takeGlobalCursor"===i.type&&e.setBrushOption("brush"===i.key?i.brushOption:{brushType:!1}),(e.brushTargetManager=new hy(e.option,t)).setInputRanges(e.areas,t)})}),Bs(GN,function(t,e,n){var o,a,s=[];t.eachComponent({mainType:"brush"},function(e,n){function l(t){return"all"===m||v[t]}function u(t){return!!t.length}function h(t,e){var i=t.coordinateSystem;w|=i.hasAxisBrushed(),l(e)&&i.eachActiveState(t.getData(),function(t,e){"active"===t&&(x[e]=1)})}function c(i,n,o){var a=_y(i);if(a&&!wy(e,n)&&(d(b,function(n){a[n.brushType]&&e.brushTargetManager.controlSeries(n,i,t)&&o.push(n),w|=u(o)}),l(n)&&u(o))){var r=i.getData();r.each(function(t){xy(a,o,r,t)&&(x[t]=1)})}}var p={brushId:e.id,brushIndex:n,brushName:e.name,areas:i(e.areas),selected:[]};s.push(p);var g=e.option,m=g.brushLink,v=[],x=[],_=[],w=0;n||(o=g.throttleType,a=g.throttleDelay);var b=f(e.areas,function(t){return by(r({boundingRect:FN[t.brushType](t)},t))}),S=ty(e.option,zN,function(t){t.mappingMethod="fixed"});y(m)&&d(m,function(t){v[t]=1}),t.eachSeries(function(t,e){var i=_[e]=[];"parallel"===t.subType?h(t,e):c(t,e,i)}),t.eachSeries(function(t,e){var i={seriesId:t.id,seriesIndex:e,seriesName:t.name,dataIndex:[]};p.selected.push(i);var n=_y(t),o=_[e],a=t.getData(),r=l(e)?function(t){return x[t]?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"}:function(t){return xy(n,o,a,t)?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"};(l(e)?w:u(o))&&iy(zN,S,a,r)})}),vy(e,o,a,s,n)});var FN={lineX:B,lineY:B,rect:function(t){return Sy(t.range)},polygon:function(t){for(var e,i=t.range,n=0,o=i.length;ne[0][1]&&(e[0][1]=a[0]),a[1]e[1][1]&&(e[1][1]=a[1])}return e&&Sy(e)}},WN=["#ddd"];Fs({type:"brush",dependencies:["geo","grid","xAxis","yAxis","parallel","series"],defaultOption:{toolbox:null,brushLink:null,seriesIndex:"all",geoIndex:null,xAxisIndex:null,yAxisIndex:null,brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(120,140,180,0.3)",borderColor:"rgba(120,140,180,0.8)"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},areas:[],brushType:null,brushOption:{},coordInfoList:[],optionUpdated:function(t,e){var i=this.option;!e&&ey(i,t,["inBrush","outOfBrush"]);var n=i.inBrush=i.inBrush||{};i.outOfBrush=i.outOfBrush||{color:WN},n.hasOwnProperty("liftZ")||(n.liftZ=5)},setAreas:function(t){t&&(this.areas=f(t,function(t){return My(this.option,t)},this))},setBrushOption:function(t){this.brushOption=My(this.option,t),this.brushType=this.brushOption.brushType}});Ws({type:"brush",init:function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new zf(e.getZr())).on("brush",m(this._onBrush,this)).mount()},render:function(t){return this.model=t,Iy.apply(this,arguments)},updateTransform:Iy,updateView:Iy,dispose:function(){this._brushController.dispose()},_onBrush:function(t,e){var n=this.model.id;this.model.brushTargetManager.setOutputRanges(t,this.ecModel),(!e.isEnd||e.removeOnClick)&&this.api.dispatchAction({type:"brush",brushId:n,areas:i(t),$from:n})}}),Es({type:"brush",event:"brush"},function(t,e){e.eachComponent({mainType:"brush",query:t},function(e){e.setAreas(t.areas)})}),Es({type:"brushSelect",event:"brushSelected",update:"none"},function(){});var HN={},ZN=rT.toolbox.brush;Dy.defaultOption={show:!0,type:["rect","polygon","lineX","lineY","keep","clear"],icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:i(ZN.title)};var UN=Dy.prototype;UN.render=UN.updateView=function(t,e,i){var n,o,a;e.eachComponent({mainType:"brush"},function(t){n=t.brushType,o=t.brushOption.brushMode||"single",a|=t.areas.length}),this._brushType=n,this._brushMode=o,d(t.get("type",!0),function(e){t.setIconStatus(e,("keep"===e?"multiple"===o:"clear"===e?a:e===n)?"emphasis":"normal")})},UN.getIcons=function(){var t=this.model,e=t.get("icon",!0),i={};return d(t.get("type",!0),function(t){e[t]&&(i[t]=e[t])}),i},UN.onclick=function(t,e,i){var n=this._brushType,o=this._brushMode;"clear"===i?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===i?n:n!==i&&i,brushMode:"keep"===i?"multiple"===o?"single":"multiple":o}})},Ty("brush",Dy),Ns(function(t,e){var i=t&&t.brush;if(y(i)||(i=i?[i]:[]),i.length){var n=[];d(i,function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(n=n.concat(e))});var o=t&&t.toolbox;y(o)&&(o=o[0]),o||(o={feature:{}},t.toolbox=[o]);var a=o.feature||(o.feature={}),r=a.brush||(a.brush={}),s=r.type||(r.type=[]);s.push.apply(s,n),Jv(s),e&&!s.length&&s.push.apply(s,SN)}});Cy.prototype={constructor:Cy,type:"calendar",dimensions:["time","value"],getDimensionsInfo:function(){return[{name:"time",type:"time"},"value"]},getRangeInfo:function(){return this._rangeInfo},getModel:function(){return this._model},getRect:function(){return this._rect},getCellWidth:function(){return this._sw},getCellHeight:function(){return this._sh},getOrient:function(){return this._orient},getFirstDayOfWeek:function(){return this._firstDayOfWeek},getDateInfo:function(t){var e=(t=Yo(t)).getFullYear(),i=t.getMonth()+1;i=i<10?"0"+i:i;var n=t.getDate();n=n<10?"0"+n:n;var o=t.getDay();return o=Math.abs((o+7-this.getFirstDayOfWeek())%7),{y:e,m:i,d:n,day:o,time:t.getTime(),formatedDate:e+"-"+i+"-"+n,date:t}},getNextNDay:function(t,e){return 0===(e=e||0)?this.getDateInfo(t):((t=new Date(this.getDateInfo(t).time)).setDate(t.getDate()+e),this.getDateInfo(t))},update:function(t,e){function i(t,e){return null!=t[e]&&"auto"!==t[e]}this._firstDayOfWeek=+this._model.getModel("dayLabel").get("firstDay"),this._orient=this._model.get("orient"),this._lineWidth=this._model.getModel("itemStyle").getItemStyle().lineWidth||0,this._rangeInfo=this._getRangeInfo(this._initRangeOption());var n=this._rangeInfo.weeks||1,o=["width","height"],a=this._model.get("cellSize").slice(),r=this._model.getBoxLayoutParams(),s="horizontal"===this._orient?[n,7]:[7,n];d([0,1],function(t){i(a,t)&&(r[o[t]]=a[t]*s[t])});var l={width:e.getWidth(),height:e.getHeight()},u=this._rect=ca(r,l);d([0,1],function(t){i(a,t)||(a[t]=u[o[t]]/s[t])}),this._sw=a[0],this._sh=a[1]},dataToPoint:function(t,e){y(t)&&(t=t[0]),null==e&&(e=!0);var i=this.getDateInfo(t),n=this._rangeInfo,o=i.formatedDate;if(e&&!(i.time>=n.start.time&&i.timea.end.time&&t.reverse(),t},_getRangeInfo:function(t){var e;(t=[this.getDateInfo(t[0]),this.getDateInfo(t[1])])[0].time>t[1].time&&(e=!0,t.reverse());var i=Math.floor(t[1].time/864e5)-Math.floor(t[0].time/864e5)+1,n=new Date(t[0].time),o=n.getDate(),a=t[1].date.getDate();if(n.setDate(o+i-1),n.getDate()!==a)for(var r=n.getTime()-t[1].time>0?1:-1;n.getDate()!==a&&(n.getTime()-t[1].time)*r>0;)i-=r,n.setDate(o+i-1);var s=Math.floor((i+t[0].day+6)/7),l=e?1-s:s-1;return e&&t.reverse(),{range:[t[0].formatedDate,t[1].formatedDate],start:t[0],end:t[1],allDay:i,weeks:s,nthWeek:l,fweek:t[0].day,lweek:t[1].day}},_getDateByWeeksAndDay:function(t,e,i){var n=this._getRangeInfo(i);if(t>n.weeks||0===t&&en.lweek)return!1;var o=7*(t-1)-n.fweek+e,a=new Date(n.start.time);return a.setDate(n.start.d+o),this.getDateInfo(a)}},Cy.dimensions=Cy.prototype.dimensions,Cy.getDimensionsInfo=Cy.prototype.getDimensionsInfo,Cy.create=function(t,e){var i=[];return t.eachComponent("calendar",function(n){var o=new Cy(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeries(function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("calendarIndex")||0])}),i},Fa.register("calendar",Cy);var XN=lI.extend({type:"calendar",coordinateSystem:null,defaultOption:{zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},init:function(t,e,i,n){var o=ga(t);XN.superApply(this,"init",arguments),ky(t,o)},mergeOption:function(t,e){XN.superApply(this,"mergeOption",arguments),ky(this.option,t)}}),jN={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},YN={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]};Ws({type:"calendar",_tlpoints:null,_blpoints:null,_firstDayOfMonth:null,_firstDayPoints:null,render:function(t,e,i){var n=this.group;n.removeAll();var o=t.coordinateSystem,a=o.getRangeInfo(),r=o.getOrient();this._renderDayRect(t,a,n),this._renderLines(t,a,r,n),this._renderYearText(t,a,r,n),this._renderMonthText(t,r,n),this._renderWeekText(t,a,r,n)},_renderDayRect:function(t,e,i){for(var n=t.coordinateSystem,o=t.getModel("itemStyle").getItemStyle(),a=n.getCellWidth(),r=n.getCellHeight(),s=e.start.time;s<=e.end.time;s=n.getNextNDay(s,1).time){var l=n.dataToRect([s],!1).tl,u=new yM({shape:{x:l[0],y:l[1],width:a,height:r},cursor:"default",style:o});i.add(u)}},_renderLines:function(t,e,i,n){function o(e){a._firstDayOfMonth.push(r.getDateInfo(e)),a._firstDayPoints.push(r.dataToRect([e],!1).tl);var o=a._getLinePointsOfOneWeek(t,e,i);a._tlpoints.push(o[0]),a._blpoints.push(o[o.length-1]),l&&a._drawSplitline(o,s,n)}var a=this,r=t.coordinateSystem,s=t.getModel("splitLine.lineStyle").getLineStyle(),l=t.get("splitLine.show"),u=s.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var h=e.start,c=0;h.time<=e.end.time;c++){o(h.formatedDate),0===c&&(h=r.getDateInfo(e.start.y+"-"+e.start.m));var d=h.date;d.setMonth(d.getMonth()+1),h=r.getDateInfo(d)}o(r.getNextNDay(e.end.time,1).formatedDate),l&&this._drawSplitline(a._getEdgesPoints(a._tlpoints,u,i),s,n),l&&this._drawSplitline(a._getEdgesPoints(a._blpoints,u,i),s,n)},_getEdgesPoints:function(t,e,i){var n=[t[0].slice(),t[t.length-1].slice()],o="horizontal"===i?0:1;return n[0][o]=n[0][o]-e/2,n[1][o]=n[1][o]+e/2,n},_drawSplitline:function(t,e,i){var n=new gM({z2:20,shape:{points:t},style:e});i.add(n)},_getLinePointsOfOneWeek:function(t,e,i){var n=t.coordinateSystem;e=n.getDateInfo(e);for(var o=[],a=0;a<7;a++){var r=n.getNextNDay(e.time,a),s=n.dataToRect([r.time],!1);o[2*r.day]=s.tl,o[2*r.day+1]=s["horizontal"===i?"bl":"tr"]}return o},_formatterLabel:function(t,e){return"string"==typeof t&&t?oa(t,e):"function"==typeof t?t(e):e.nameMap},_yearTextPositionControl:function(t,e,i,n,o){e=e.slice();var a=["center","bottom"];"bottom"===n?(e[1]+=o,a=["center","top"]):"left"===n?e[0]-=o:"right"===n?(e[0]+=o,a=["center","top"]):e[1]-=o;var r=0;return"left"!==n&&"right"!==n||(r=Math.PI/2),{rotation:r,position:e,style:{textAlign:a[0],textVerticalAlign:a[1]}}},_renderYearText:function(t,e,i,n){var o=t.getModel("yearLabel");if(o.get("show")){var a=o.get("margin"),r=o.get("position");r||(r="horizontal"!==i?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===i?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var f=o.get("formatter"),p={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(f,p),m=new rM({z2:30});mo(m.style,o,{text:g}),m.attr(this._yearTextPositionControl(m,c[r],i,r,a)),n.add(m)}},_monthTextPositionControl:function(t,e,i,n,o){var a="left",r="top",s=t[0],l=t[1];return"horizontal"===i?(l+=o,e&&(a="center"),"start"===n&&(r="bottom")):(s+=o,e&&(r="middle"),"start"===n&&(a="right")),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderMonthText:function(t,e,i){var n=t.getModel("monthLabel");if(n.get("show")){var o=n.get("nameMap"),r=n.get("margin"),s=n.get("position"),l=n.get("align"),u=[this._tlpoints,this._blpoints];_(o)&&(o=jN[o.toUpperCase()]||[]);var h="start"===s?0:1,c="horizontal"===e?0:1;r="start"===s?-r:r;for(var d="center"===l,f=0;f=r[0]&&t<=r[1]}if(t===this._dataZoomModel){var n=this._dimName,o=this.getTargetSeriesModels(),a=t.get("filterMode"),r=this._valueWindow;"none"!==a&&$N(o,function(t){var e=t.getData(),o=e.mapDimension(n,!0);o.length&&("weakFilter"===a?e.filterSelf(function(t){for(var i,n,a,s=0;sr[1];if(u&&!h&&!c)return!0;u&&(a=!0),h&&(i=!0),c&&(n=!0)}return a&&i&&n}):$N(o,function(n){if("empty"===a)t.setData(e.map(n,function(t){return i(t)?t:NaN}));else{var o={};o[n]=r,e.selectRange(o)}}),$N(o,function(t){e.setApproximateExtent(r,t)}))})}}};var tO=d,eO=KN,iO=Fs({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,i){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var n=By(t);this.mergeDefaultAndTheme(t,i),this.doInit(n)},mergeOption:function(t){var e=By(t);n(this.option,t,!0),this.doInit(e)},doInit:function(t){var e=this.option;U_.canvasSupported||(e.realtime=!1),this._setDefaultThrottle(t),Vy(this,t),tO([["start","startValue"],["end","endValue"]],function(t,i){"value"===this._rangePropMode[i]&&(e[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var t=this._axisProxies;this.eachTargetAxis(function(e,i,n,o){var a=this.dependentModels[e.axis][i],r=a.__dzAxisProxy||(a.__dzAxisProxy=new QN(e.name,i,this,o));t[e.name+"_"+i]=r},this)},_resetTarget:function(){var t=this.option,e=this._judgeAutoMode();eO(function(e){var i=e.axisIndex;t[i]=Di(t[i])},this),"axisIndex"===e?this._autoSetAxisIndex():"orient"===e&&this._autoSetOrient()},_judgeAutoMode:function(){var t=this.option,e=!1;eO(function(i){null!=t[i.axisIndex]&&(e=!0)},this);var i=t.orient;return null==i&&e?"orient":e?void 0:(null==i&&(t.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var t=!0,e=this.get("orient",!0),i=this.option,n=this.dependentModels;if(t){var o="vertical"===e?"y":"x";n[o+"Axis"].length?(i[o+"AxisIndex"]=[0],t=!1):tO(n.singleAxis,function(n){t&&n.get("orient",!0)===e&&(i.singleAxisIndex=[n.componentIndex],t=!1)})}t&&eO(function(e){if(t){var n=[],o=this.dependentModels[e.axis];if(o.length&&!n.length)for(var a=0,r=o.length;a0?100:20}},getFirstTargetAxisModel:function(){var t;return eO(function(e){if(null==t){var i=this.get(e.axisIndex);i.length&&(t=this.dependentModels[e.axis][i[0]])}},this),t},eachTargetAxis:function(t,e){var i=this.ecModel;eO(function(n){tO(this.get(n.axisIndex),function(o){t.call(e,n,o,this,i)},this)},this)},getAxisProxy:function(t,e){return this._axisProxies[t+"_"+e]},getAxisModel:function(t,e){var i=this.getAxisProxy(t,e);return i&&i.getAxisModel()},setRawRange:function(t,e){var i=this.option;tO([["start","startValue"],["end","endValue"]],function(e){null==t[e[0]]&&null==t[e[1]]||(i[e[0]]=t[e[0]],i[e[1]]=t[e[1]])},this),!e&&Vy(this,t)},getPercentRange:function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},getValueRange:function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var i=this.findRepresentativeAxisProxy();return i?i.getDataValueWindow():void 0},findRepresentativeAxisProxy:function(t){if(t)return t.__dzAxisProxy;var e=this._axisProxies;for(var i in e)if(e.hasOwnProperty(i)&&e[i].hostedBy(this))return e[i];for(var i in e)if(e.hasOwnProperty(i)&&!e[i].hostedBy(this))return e[i]},getRangePropMode:function(){return this._rangePropMode.slice()}}),nO=qI.extend({type:"dataZoom",render:function(t,e,i,n){this.dataZoomModel=t,this.ecModel=e,this.api=i},getTargetCoordInfo:function(){function t(t,e,i,n){for(var o,a=0;a0&&e%g)p+=f;else{var i=null==t||isNaN(t)||""===t,n=i?0:aO(t,a,u,!0);i&&!l&&e?(c.push([c[c.length-1][0],0]),d.push([d[d.length-1][0],0])):!i&&l&&(c.push([p,0]),d.push([p,0])),c.push([p,n]),d.push([p,n]),p+=f,l=i}});var m=this.dataZoomModel;this._displayables.barGroup.add(new pM({shape:{points:c},style:r({fill:m.get("dataBackgroundColor")},m.getModel("dataBackground.areaStyle").getAreaStyle()),silent:!0,z2:-20})),this._displayables.barGroup.add(new gM({shape:{points:d},style:m.getModel("dataBackground.lineStyle").getLineStyle(),silent:!0,z2:-19}))}}},_prepareDataShadowInfo:function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var i,n=this.ecModel;return t.eachTargetAxis(function(o,a){d(t.getAxisProxy(o.name,a).getTargetSeriesModels(),function(t){if(!(i||!0!==e&&l(cO,t.get("type"))<0)){var r,s=n.getComponent(o.axis,a).axis,u=Gy(o.name),h=t.coordinateSystem;null!=u&&h.getOtherAxis&&(r=h.getOtherAxis(s).inverse),u=t.getData().mapDimension(u),i={thisAxis:s,series:t,thisDim:o.name,otherDim:u,otherAxisInverse:r}}},this)},this),i}},_renderHandle:function(){var t=this._displayables,e=t.handles=[],i=t.handleLabels=[],n=this._displayables.barGroup,o=this._size,a=this.dataZoomModel;n.add(t.filler=new oO({draggable:!0,cursor:Fy(this._orient),drift:sO(this._onDragMove,this,"all"),onmousemove:function(t){mw(t.event)},ondragstart:sO(this._showDataInfo,this,!0),ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1),style:{fill:a.get("fillerColor"),textPosition:"inside"}})),n.add(new oO($n({silent:!0,shape:{x:0,y:0,width:o[0],height:o[1]},style:{stroke:a.get("dataBackgroundColor")||a.get("borderColor"),lineWidth:1,fill:"rgba(0,0,0,0)"}}))),lO([0,1],function(t){var o=Po(a.get("handleIcon"),{cursor:Fy(this._orient),draggable:!0,drift:sO(this._onDragMove,this,t),onmousemove:function(t){mw(t.event)},ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1)},{x:-1,y:0,width:2,height:2}),r=o.getBoundingRect();this._handleHeight=Vo(a.get("handleSize"),this._size[1]),this._handleWidth=r.width/r.height*this._handleHeight,o.setStyle(a.getModel("handleStyle").getItemStyle());var s=a.get("handleColor");null!=s&&(o.style.fill=s),n.add(e[t]=o);var l=a.textStyleModel;this.group.add(i[t]=new rM({silent:!0,invisible:!0,style:{x:0,y:0,text:"",textVerticalAlign:"middle",textAlign:"center",textFill:l.getTextColor(),textFont:l.getFont()},z2:10}))},this)},_resetInterval:function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[aO(t[0],[0,100],e,!0),aO(t[1],[0,100],e,!0)]},_updateInterval:function(t,e){var i=this.dataZoomModel,n=this._handleEnds,o=this._getViewExtent(),a=i.findRepresentativeAxisProxy().getMinMaxSpan(),r=[0,100];QL(e,n,o,i.get("zoomLock")?"all":t,null!=a.minSpan?aO(a.minSpan,r,o,!0):null,null!=a.maxSpan?aO(a.maxSpan,r,o,!0):null);var s=this._range,l=this._range=rO([aO(n[0],o,r,!0),aO(n[1],o,r,!0)]);return!s||s[0]!==l[0]||s[1]!==l[1]},_updateView:function(t){var e=this._displayables,i=this._handleEnds,n=rO(i.slice()),o=this._size;lO([0,1],function(t){var n=e.handles[t],a=this._handleHeight;n.attr({scale:[a/2,a/2],position:[i[t],o[1]/2-a/2]})},this),e.filler.setShape({x:n[0],y:0,width:n[1]-n[0],height:o[1]}),this._updateDataInfo(t)},_updateDataInfo:function(t){function e(t){var e=Ao(n.handles[t].parent,this.group),i=Co(0===t?"right":"left",e),s=this._handleWidth/2+hO,l=Do([c[t]+(0===t?-s:s),this._size[1]/2],e);o[t].setStyle({x:l[0],y:l[1],textVerticalAlign:a===uO?"middle":i,textAlign:a===uO?i:"center",text:r[t]})}var i=this.dataZoomModel,n=this._displayables,o=n.handleLabels,a=this._orient,r=["",""];if(i.get("showDetail")){var s=i.findRepresentativeAxisProxy();if(s){var l=s.getAxisModel().axis,u=this._range,h=t?s.calculateDataWindow({start:u[0],end:u[1]}).valueWindow:s.getDataValueWindow();r=[this._formatLabel(h[0],l),this._formatLabel(h[1],l)]}}var c=rO(this._handleEnds.slice());e.call(this,0),e.call(this,1)},_formatLabel:function(t,e){var i=this.dataZoomModel,n=i.get("labelFormatter"),o=i.get("labelPrecision");null!=o&&"auto"!==o||(o=e.getPixelPrecision());var a=null==t||isNaN(t)?"":"category"===e.type||"time"===e.type?e.scale.getLabel(Math.round(t)):t.toFixed(Math.min(o,20));return x(n)?n(t,a):_(n)?n.replace("{value}",a):a},_showDataInfo:function(t){t=this._dragging||t;var e=this._displayables.handleLabels;e[0].attr("invisible",!t),e[1].attr("invisible",!t)},_onDragMove:function(t,e,i){this._dragging=!0;var n=Do([e,i],this._displayables.barGroup.getLocalTransform(),!0),o=this._updateInterval(t,n[0]),a=this.dataZoomModel.get("realtime");this._updateView(!a),o&&a&&this._dispatchZoomAction()},_onDragEnd:function(){this._dragging=!1,this._showDataInfo(!1),!this.dataZoomModel.get("realtime")&&this._dispatchZoomAction()},_onClickPanelClick:function(t){var e=this._size,i=this._displayables.barGroup.transformCoordToLocal(t.offsetX,t.offsetY);if(!(i[0]<0||i[0]>e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var t;if(lO(this.getTargetCoordInfo(),function(e){if(!t&&e.length){var i=e[0].model.coordinateSystem;t=i.getRect&&i.getRect()}}),!t){var e=this.api.getWidth(),i=this.api.getHeight();t={x:.2*e,y:.2*i,width:.6*e,height:.6*i}}return t}});iO.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var fO="\0_ec_dataZoom_roams",pO=m,gO=nO.extend({type:"dataZoom.inside",init:function(t,e){this._range},render:function(t,e,i,n){gO.superApply(this,"render",arguments),this._range=t.getPercentRange(),d(this.getTargetCoordInfo(),function(e,n){var o=f(e,function(t){return Zy(t.model)});d(e,function(e){var a=e.model,r={};d(["pan","zoom","scrollMove"],function(t){r[t]=pO(mO[t],this,e,n)},this),Wy(i,{coordId:Zy(a),allCoordIds:o,containsPoint:function(t,e,i){return a.coordinateSystem.containPoint([e,i])},dataZoomId:t.id,dataZoomModel:t,getRange:r})},this)},this)},dispose:function(){Hy(this.api,this.dataZoomModel.id),gO.superApply(this,"dispose",arguments),this._range=null}}),mO={zoom:function(t,e,i,n){var o=this._range,a=o.slice(),r=t.axisModels[0];if(r){var s=vO[e](null,[n.originX,n.originY],r,i,t),l=(s.signal>0?s.pixelStart+s.pixelLength-s.pixel:s.pixel-s.pixelStart)/s.pixelLength*(a[1]-a[0])+a[0],u=Math.max(1/n.scale,0);a[0]=(a[0]-l)*u+l,a[1]=(a[1]-l)*u+l;var h=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return QL(0,a,[0,100],0,h.minSpan,h.maxSpan),this._range=a,o[0]!==a[0]||o[1]!==a[1]?a:void 0}},pan:Ky(function(t,e,i,n,o,a){var r=vO[n]([a.oldX,a.oldY],[a.newX,a.newY],e,o,i);return r.signal*(t[1]-t[0])*r.pixel/r.pixelLength}),scrollMove:Ky(function(t,e,i,n,o,a){return vO[n]([0,0],[a.scrollDelta,a.scrollDelta],e,o,i).signal*(t[1]-t[0])*a.scrollDelta})},vO={grid:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem.getRect();return t=t||[0,0],"x"===a.dim?(r.pixel=e[0]-t[0],r.pixelLength=s.width,r.pixelStart=s.x,r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=s.height,r.pixelStart=s.y,r.signal=a.inverse?-1:1),r},polar:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),u=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===i.mainType?(r.pixel=e[0]-t[0],r.pixelLength=l[1]-l[0],r.pixelStart=l[0],r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=u[1]-u[0],r.pixelStart=u[0],r.signal=a.inverse?-1:1),r},singleAxis:function(t,e,i,n,o){var a=i.axis,r=o.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===a.orient?(s.pixel=e[0]-t[0],s.pixelLength=r.width,s.pixelStart=r.x,s.signal=a.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=r.height,s.pixelStart=r.y,s.signal=a.inverse?-1:1),s}};Os({getTargetSeries:function(t){var e=R();return t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){d(n.getAxisProxy(t.name,i).getTargetSeriesModels(),function(t){e.set(t.uid,t)})})}),e},modifyOutputEnd:!0,overallReset:function(t,e){t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).reset(n,e)}),t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).filterData(n,e)})}),t.eachComponent("dataZoom",function(t){var e=t.findRepresentativeAxisProxy(),i=e.getDataPercentWindow(),n=e.getDataValueWindow();t.setRawRange({start:i[0],end:i[1],startValue:n[0],endValue:n[1]},!0)})}}),Es("dataZoom",function(t,e){var i=Ny(m(e.eachComponent,e,"dataZoom"),KN,function(t,e){return t.get(e.axisIndex)}),n=[];e.eachComponent({mainType:"dataZoom",query:t},function(t,e){n.push.apply(n,i(t).nodes)}),d(n,function(e,i){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})})});var yO=d,xO=function(t){var e=t&&t.visualMap;y(e)||(e=e?[e]:[]),yO(e,function(t){if(t){$y(t,"splitList")&&!$y(t,"pieces")&&(t.pieces=t.splitList,delete t.splitList);var e=t.pieces;e&&y(e)&&yO(e,function(t){w(t)&&($y(t,"start")&&!$y(t,"min")&&(t.min=t.start),$y(t,"end")&&!$y(t,"max")&&(t.max=t.end))})}})};lI.registerSubTypeDefaulter("visualMap",function(t){return t.categories||(t.pieces?t.pieces.length>0:t.splitNumber>0)&&!t.calculable?"piecewise":"continuous"});var _O=VT.VISUAL.COMPONENT;Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=[];return e.eachComponent("visualMap",function(e){var n=t.pipelineContext;!e.isTargetSeries(t)||n&&n.large||i.push(ny(e.stateList,e.targetVisuals,m(e.getValueState,e),e.getDataDimension(t.getData())))}),i}}),Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=t.getData(),n=[];e.eachComponent("visualMap",function(e){if(e.isTargetSeries(t)){var o=e.getVisualMeta(m(Jy,null,t,e))||{stops:[],outerColors:[]},a=e.getDataDimension(i),r=i.getDimensionInfo(a);null!=r&&(o.dimension=r.index,n.push(o))}}),t.getData().setVisual("visualMeta",n)}});var wO={get:function(t,e,n){var o=i((bO[t]||{})[e]);return n&&y(o)?o[o.length-1]:o}},bO={color:{active:["#006edd","#e0ffff"],inactive:["rgba(0,0,0,0)"]},colorHue:{active:[0,360],inactive:[0,0]},colorSaturation:{active:[.3,1],inactive:[0,0]},colorLightness:{active:[.9,.5],inactive:[0,0]},colorAlpha:{active:[.3,1],inactive:[0,0]},opacity:{active:[.3,1],inactive:[0,0]},symbol:{active:["circle","roundRect","diamond"],inactive:["none"]},symbolSize:{active:[10,50],inactive:[0,0]}},SO=hL.mapVisual,MO=hL.eachVisual,IO=y,TO=d,AO=Fo,DO=Bo,CO=B,LO=Fs({type:"visualMap",dependencies:["series"],stateList:["inRange","outOfRange"],replacableOptionKeys:["inRange","outOfRange","target","controller","color"],dataBound:[-1/0,1/0],layoutMode:{type:"box",ignoreSize:!0},defaultOption:{show:!0,zlevel:0,z:4,seriesIndex:"all",min:0,max:200,dimension:null,inRange:null,outOfRange:null,left:0,right:null,top:null,bottom:0,itemWidth:null,itemHeight:null,inverse:!1,orient:"vertical",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",contentColor:"#5793f3",inactiveColor:"#aaa",borderWidth:0,padding:5,textGap:10,precision:0,color:null,formatter:null,text:null,textStyle:{color:"#333"}},init:function(t,e,i){this._dataExtent,this.targetVisuals={},this.controllerVisuals={},this.textStyleModel,this.itemSize,this.mergeDefaultAndTheme(t,i)},optionUpdated:function(t,e){var i=this.option;U_.canvasSupported||(i.realtime=!1),!e&&ey(i,t,this.replacableOptionKeys),this.textStyleModel=this.getModel("textStyle"),this.resetItemSize(),this.completeVisualOption()},resetVisual:function(t){var e=this.stateList;t=m(t,this),this.controllerVisuals=ty(this.option.controller,e,t),this.targetVisuals=ty(this.option.target,e,t)},getTargetSeriesIndices:function(){var t=this.option.seriesIndex,e=[];return null==t||"all"===t?this.ecModel.eachSeries(function(t,i){e.push(i)}):e=Di(t),e},eachTargetSeries:function(t,e){d(this.getTargetSeriesIndices(),function(i){t.call(e,this.ecModel.getSeriesByIndex(i))},this)},isTargetSeries:function(t){var e=!1;return this.eachTargetSeries(function(i){i===t&&(e=!0)}),e},formatValueText:function(t,e,i){function n(t){return t===l[0]?"min":t===l[1]?"max":(+t).toFixed(Math.min(s,20))}var o,a,r=this.option,s=r.precision,l=this.dataBound,u=r.formatter;return i=i||["<",">"],y(t)&&(t=t.slice(),o=!0),a=e?t:o?[n(t[0]),n(t[1])]:n(t),_(u)?u.replace("{value}",o?a[0]:a).replace("{value2}",o?a[1]:a):x(u)?o?u(t[0],t[1]):u(t):o?t[0]===l[0]?i[0]+" "+a[1]:t[1]===l[1]?i[1]+" "+a[0]:a[0]+" - "+a[1]:a},resetExtent:function(){var t=this.option,e=AO([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;o>=0;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){function t(t){IO(o.color)&&!t.inRange&&(t.inRange={color:o.color.slice().reverse()}),t.inRange=t.inRange||{color:e.get("gradientColor")},TO(this.stateList,function(e){var i=t[e];if(_(i)){var n=wO.get(i,"active",l);n?(t[e]={},t[e][i]=n):delete t[e]}},this)}var e=this.ecModel,o=this.option,a={inRange:o.inRange,outOfRange:o.outOfRange},r=o.target||(o.target={}),s=o.controller||(o.controller={});n(r,a),n(s,a);var l=this.isCategory();t.call(this,r),t.call(this,s),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},TO(n,function(t,e){if(hL.isValidType(e)){var i=wO.get(e,"inactive",l);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,r,"inRange","outOfRange"),function(t){var e=(t.inRange||{}).symbol||(t.outOfRange||{}).symbol,n=(t.inRange||{}).symbolSize||(t.outOfRange||{}).symbolSize,o=this.get("inactiveColor");TO(this.stateList,function(a){var r=this.itemSize,s=t[a];s||(s=t[a]={color:l?o:[o]}),null==s.symbol&&(s.symbol=e&&i(e)||(l?"roundRect":["roundRect"])),null==s.symbolSize&&(s.symbolSize=n&&i(n)||(l?r[0]:[r[0],r[0]])),s.symbol=SO(s.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var u=s.symbolSize;if(null!=u){var h=-1/0;MO(u,function(t){t>h&&(h=t)}),s.symbolSize=SO(u,function(t){return DO(t,[0,h],[0,r[0]],!0)})}},this)}.call(this,s)},resetItemSize:function(){this.itemSize=[parseFloat(this.get("itemWidth")),parseFloat(this.get("itemHeight"))]},isCategory:function(){return!!this.option.categories},setSelected:CO,getValueState:CO,getVisualMeta:CO}),kO=[20,140],PO=LO.extend({type:"visualMap.continuous",defaultOption:{align:"auto",calculable:!1,range:null,realtime:!0,itemHeight:null,itemWidth:null,hoverLink:!0,hoverLinkDataSize:null,hoverLinkOnHandle:null},optionUpdated:function(t,e){PO.superApply(this,"optionUpdated",arguments),this.resetExtent(),this.resetVisual(function(t){t.mappingMethod="linear",t.dataExtent=this.getExtent()}),this._resetRange()},resetItemSize:function(){PO.superApply(this,"resetItemSize",arguments);var t=this.itemSize;"horizontal"===this._orient&&t.reverse(),(null==t[0]||isNaN(t[0]))&&(t[0]=kO[0]),(null==t[1]||isNaN(t[1]))&&(t[1]=kO[1])},_resetRange:function(){var t=this.getExtent(),e=this.option.range;!e||e.auto?(t.auto=1,this.option.range=t):y(e)&&(e[0]>e[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){LO.prototype.completeVisualOption.apply(this,arguments),d(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Fo((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){t[0]<=e&&e<=t[1]&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getVisualMeta:function(t){function e(e,i){o.push({value:e,color:t(e,i)})}for(var i=Qy(0,0,this.getExtent()),n=Qy(0,0,this.option.range.slice()),o=[],a=0,r=0,s=n.length,l=i.length;rt[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new tb("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(t,e){if(this._useHandle){var i=this._shapes,n=this.visualMapModel,o=i.handleThumbs,a=i.handleLabels;EO([0,1],function(r){var s=o[r];s.setStyle("fill",e.handlesColor[r]),s.position[1]=t[r];var l=Do(i.handleLabelPoints[r],Ao(s,this.group));a[r].setStyle({x:l[0],y:l[1],text:n.formatValueText(this._dataInterval[r]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===r?"bottom":"top":"left",i.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=OO(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",ox(!!i,n,l,r[1]));var c={convertOpacityToAlpha:!0},d=this.getControllerVisual(t,"color",c);h.setStyle("fill",d);var f=Do(u.indicatorLabelPoint,Ao(h,this.group)),p=u.indicatorLabel;p.attr("invisible",!1);var g=this._applyTransform("left",u.barGroup),m=this._orient;p.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===m?g:"middle",textAlign:"horizontal"===m?"center":g,x:f[0],y:f[1]})}},_enableHoverLinkToSeries:function(){var t=this;this._shapes.barGroup.on("mousemove",function(e){if(t._hovering=!0,!t._dragging){var i=t.visualMapModel.itemSize,n=t._applyTransform([e.offsetX,e.offsetY],t._shapes.barGroup,!0,!0);n[1]=RO(zO(0,n[1]),i[1]),t._doHoverLinkToSeries(n[1],0<=n[0]&&n[0]<=i[0])}}).on("mouseout",function(){t._hovering=!1,!t._dragging&&t._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=RO(zO(o[0],t),o[1]);var r=ax(i,a,o),s=[t-r,t+r],l=OO(t,o,a,!0),u=[OO(s[0],o,a,!0),OO(s[1],o,a,!0)];s[0]o[1]&&(u[1]=1/0),e&&(u[0]===-1/0?this._showIndicator(l,u[1],"< ",r):u[1]===1/0?this._showIndicator(l,u[0],"> ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||rx(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=Ri(h,c);this._dispatchHighDown("downplay",ex(d[0])),this._dispatchHighDown("highlight",ex(d[1]))}},_hoverLinkFromSeriesMouseOver:function(t){var e=t.target,i=this.visualMapModel;if(e&&null!=e.dataIndex){var n=this.ecModel.getSeriesByIndex(e.seriesIndex);if(i.isTargetSeries(n)){var o=n.getData(e.dataType),a=o.get(i.getDataDimension(o),e.dataIndex,!0);isNaN(a)||this._showIndicator(a,a)}}},_hideIndicator:function(){var t=this._shapes;t.indicator&&t.indicator.attr("invisible",!0),t.indicatorLabel&&t.indicatorLabel.attr("invisible",!0)},_clearHoverLinkToSeries:function(){this._hideIndicator();var t=this._hoverLinkDataIndices;this._dispatchHighDown("downplay",ex(t)),t.length=0},_clearHoverLinkFromSeries:function(){this._hideIndicator();var t=this.api.getZr();t.off("mouseover",this._hoverLinkFromSeriesMouseOver),t.off("mouseout",this._hideIndicator)},_applyTransform:function(t,e,i,n){var o=Ao(e,n?null:this.group);return zM[y(t)?"applyTransform":"transformDirection"](t,o,i)},_dispatchHighDown:function(t,e){e&&e.length&&this.api.dispatchAction({type:t,batch:e})},dispose:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()},remove:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()}});Es({type:"selectDataRange",event:"dataRangeSelected",update:"update"},function(t,e){e.eachComponent({mainType:"visualMap",query:t},function(e){e.setSelected(t.selected)})}),Ns(xO);var FO=LO.extend({type:"visualMap.piecewise",defaultOption:{selected:null,minOpen:!1,maxOpen:!1,align:"auto",itemWidth:20,itemHeight:14,itemSymbol:"roundRect",pieceList:null,categories:null,splitNumber:5,selectedMode:"multiple",itemGap:10,hoverLink:!0,showLabel:null},optionUpdated:function(t,e){FO.superApply(this,"optionUpdated",arguments),this._pieceList=[],this.resetExtent();var n=this._mode=this._determineMode();WO[this._mode].call(this),this._resetSelected(t,e);var o=this.option.categories;this.resetVisual(function(t,e){"categories"===n?(t.mappingMethod="category",t.categories=i(o)):(t.dataExtent=this.getExtent(),t.mappingMethod="piecewise",t.pieceList=f(this._pieceList,function(t){var t=i(t);return"inRange"!==e&&(t.visual=null),t}))})},completeVisualOption:function(){function t(t,e,i){return t&&t[e]&&(w(t[e])?t[e].hasOwnProperty(i):t[e]===i)}var e=this.option,i={},n=hL.listVisualTypes(),o=this.isCategory();d(e.pieces,function(t){d(n,function(e){t.hasOwnProperty(e)&&(i[e]=1)})}),d(i,function(i,n){var a=0;d(this.stateList,function(i){a|=t(e,i,n)||t(e.target,i,n)},this),!a&&d(this.stateList,function(t){(e[t]||(e[t]={}))[n]=wO.get(n,"inRange"===t?"active":"inactive",o)})},this),LO.prototype.completeVisualOption.apply(this,arguments)},_resetSelected:function(t,e){var i=this.option,n=this._pieceList,o=(e?i:t).selected||{};if(i.selected=o,d(n,function(t,e){var i=this.getSelectedMapKey(t);o.hasOwnProperty(i)||(o[i]=!0)},this),"single"===i.selectedMode){var a=!1;d(n,function(t,e){var i=this.getSelectedMapKey(t);o[i]&&(a?o[i]=!1:a=!0)},this)}},getSelectedMapKey:function(t){return"categories"===this._mode?t.value+"":t.index+""},getPieceList:function(){return this._pieceList},_determineMode:function(){var t=this.option;return t.pieces&&t.pieces.length>0?"pieces":this.option.categories?"categories":"splitNumber"},setSelected:function(t){this.option.selected=i(t)},getValueState:function(t){var e=hL.findPieceIndex(t,this._pieceList);return null!=e&&this.option.selected[this.getSelectedMapKey(this._pieceList[e])]?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){hL.findPieceIndex(e,this._pieceList)===t&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getRepresentValue:function(t){var e;if(this.isCategory())e=t.value;else if(null!=t.value)e=t.value;else{var i=t.interval||[];e=i[0]===-1/0&&i[1]===1/0?0:(i[0]+i[1])/2}return e},getVisualMeta:function(t){function e(e,a){var r=o.getRepresentValue({interval:e});a||(a=o.getValueState(r));var s=t(r,a);e[0]===-1/0?n[0]=s:e[1]===1/0?n[1]=s:i.push({value:e[0],color:s},{value:e[1],color:s})}if(!this.isCategory()){var i=[],n=[],o=this,a=this._pieceList.slice();if(a.length){var r=a[0].interval[0];r!==-1/0&&a.unshift({interval:[-1/0,r]}),(r=a[a.length-1].interval[1])!==1/0&&a.push({interval:[r,1/0]})}else a.push({interval:[-1/0,1/0]});var s=-1/0;return d(a,function(t){var i=t.interval;i&&(i[0]>s&&e([s,i[0]],"outOfRange"),e(i.slice()),s=i[1])},this),{stops:i,outerColors:n}}}}),WO={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i);var r=0;t.minOpen&&e.push({index:r++,interval:[-1/0,n[0]],close:[0,0]});for(var s=n[0],l=r+o;r","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};NO.extend({type:"visualMap.piecewise",doRender:function(){var t=this.group;t.removeAll();var e=this.visualMapModel,i=e.get("textGap"),n=e.textStyleModel,o=n.getFont(),a=n.getTextColor(),r=this._getItemAlign(),s=e.itemSize,l=this._getViewData(),u=l.endsText,h=T(e.get("showLabel",!0),!u);u&&this._renderEndsText(t,u[0],s,h,r),d(l.viewPieceList,function(n){var l=n.piece,u=new tb;u.onclick=m(this._onItemClick,this,l),this._enableHoverLink(u,n.indexInModelPieceList);var c=e.getRepresentValue(l);if(this._createItemSymbol(u,c,[0,0,s[0],s[1]]),h){var d=this.visualMapModel.getValueState(c);u.add(new rM({style:{x:"right"===r?-i:s[0]+i,y:s[1]/2,text:l.text,textVerticalAlign:"middle",textAlign:r,textFont:o,textFill:a,opacity:"outOfRange"===d?.5:1}}))}t.add(u)},this),u&&this._renderEndsText(t,u[1],s,h,r),aI(e.get("orient"),t,e.get("itemGap")),this.renderBackground(t),this.positionGroup(t)},_enableHoverLink:function(t,e){function i(t){var i=this.visualMapModel;i.option.hoverLink&&this.api.dispatchAction({type:t,batch:ex(i.findTargetDataIndices(e))})}t.on("mouseover",m(i,this,"highlight")).on("mouseout",m(i,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return tx(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new tb,r=this.visualMapModel.textStyleModel;a.add(new rM({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=f(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i&&(i=i.slice().reverse()),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(Jl(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,n=e.option,o=i(n.selected),a=e.getSelectedMapKey(t);"single"===n.selectedMode?(o[a]=!0,d(o,function(t,e){o[e]=e===a})):o[a]=!o[a],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:o})}});Ns(xO);var HO=ta,ZO=ia,UO=Fs({type:"marker",dependencies:["series","grid","polar","geo"],init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i),this.mergeOption(t,i,n.createdBySelf,!0)},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.__hostSeries;return this.getShallow("animation")&&t&&t.isAnimationEnabled()},mergeOption:function(t,e,i,n){var o=this.constructor,r=this.mainType+"Model";i||e.eachSeries(function(t){var i=t.get(this.mainType,!0),s=t[r];i&&i.data?(s?s.mergeOption(i,e,!0):(n&&ux(i),d(i.data,function(t){t instanceof Array?(ux(t[0]),ux(t[1])):ux(t)}),a(s=new o(i,this,e),{mainType:this.mainType,seriesIndex:t.seriesIndex,name:t.name,createdBySelf:!0}),s.__hostSeries=t),t[r]=s):t[r]=null},this)},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=y(i)?f(i,HO).join(", "):HO(i),o=e.getName(t),a=ZO(this.name);return(null!=i||o)&&(a+="
"),o&&(a+=ZO(o),null!=i&&(a+=" : ")),null!=i&&(a+=ZO(n)),a},getData:function(){return this._data},setData:function(t){this._data=t}});h(UO,ZI),UO.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var XO=l,jO=v,YO={min:jO(dx,"min"),max:jO(dx,"max"),average:jO(dx,"average")},qO=Ws({type:"marker",init:function(){this.markerGroupMap=R()},render:function(t,e,i){var n=this.markerGroupMap;n.each(function(t){t.__keep=!1});var o=this.type+"Model";e.eachSeries(function(t){var n=t[o];n&&this.renderSeries(t,n,e,i)},this),n.each(function(t){!t.__keep&&this.group.remove(t.group)},this)},renderSeries:function(){}});qO.extend({type:"markPoint",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markPointModel;e&&(xx(e.getData(),t,i),this.markerGroupMap.get(t.id).updateLayout(e))},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,r=t.getData(),s=this.markerGroupMap,l=s.get(a)||s.set(a,new Du),u=_x(o,t,e);e.setData(u),xx(e.getData(),t,n),u.each(function(t){var i=u.getItemModel(t),n=i.getShallow("symbolSize");"function"==typeof n&&(n=n(e.getRawValue(t),e.getDataParams(t))),u.setItemVisual(t,{symbolSize:n,color:i.get("itemStyle.color")||r.getVisual("color"),symbol:i.getShallow("symbol")})}),l.updateData(u),this.group.add(l.group),u.eachItemGraphicEl(function(t){t.traverse(function(t){t.dataModel=e})}),l.__keep=!0,l.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markPoint=t.markPoint||{}}),UO.extend({type:"markLine",defaultOption:{zlevel:0,z:5,symbol:["circle","arrow"],symbolSize:[8,16],precision:2,tooltip:{trigger:"item"},label:{show:!0,position:"end"},lineStyle:{type:"dashed"},emphasis:{label:{show:!0},lineStyle:{width:3}},animationEasing:"linear"}});var KO=function(t,e,o,r){var s=t.getData(),l=r.type;if(!y(r)&&("min"===l||"max"===l||"average"===l||"median"===l||null!=r.xAxis||null!=r.yAxis)){var u,h;if(null!=r.yAxis||null!=r.xAxis)u=null!=r.yAxis?"y":"x",e.getAxis(u),h=T(r.yAxis,r.xAxis);else{var c=px(r,s,e,t);u=c.valueDataDim,c.valueAxis,h=yx(s,u,l)}var d="x"===u?0:1,f=1-d,p=i(r),g={};p.type=null,p.coord=[],g.coord=[],p.coord[f]=-1/0,g.coord[f]=1/0;var m=o.get("precision");m>=0&&"number"==typeof h&&(h=+h.toFixed(Math.min(m,20))),p.coord[d]=g.coord[d]=h,r=[p,g,{type:l,valueIndex:r.valueIndex,value:h}]}return r=[fx(t,r[0]),fx(t,r[1]),a({},r[2])],r[2].type=r[2].type||"",n(r[2],r[0]),n(r[2],r[1]),r};qO.extend({type:"markLine",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markLineModel;if(e){var n=e.getData(),o=e.__from,a=e.__to;o.each(function(e){Ix(o,e,!0,t,i),Ix(a,e,!1,t,i)}),n.each(function(t){n.setItemLayout(t,[o.getItemLayout(t),a.getItemLayout(t)])}),this.markerGroupMap.get(t.id).updateLayout()}},this)},renderSeries:function(t,e,i,n){function o(e,i,o){var a=e.getItemModel(i);Ix(e,i,o,t,n),e.setItemVisual(i,{symbolSize:a.get("symbolSize")||g[o?0:1],symbol:a.get("symbol",!0)||p[o?0:1],color:a.get("itemStyle.color")||s.getVisual("color")})}var a=t.coordinateSystem,r=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(r)||l.set(r,new sf);this.group.add(u.group);var h=Tx(a,t,e),c=h.from,d=h.to,f=h.line;e.__from=c,e.__to=d,e.setData(f);var p=e.get("symbol"),g=e.get("symbolSize");y(p)||(p=[p,p]),"number"==typeof g&&(g=[g,g]),h.from.each(function(t){o(c,t,!0),o(d,t,!1)}),f.each(function(t){var e=f.getItemModel(t).get("lineStyle.color");f.setItemVisual(t,{color:e||c.getItemVisual(t,"color")}),f.setItemLayout(t,[c.getItemLayout(t),d.getItemLayout(t)]),f.setItemVisual(t,{fromSymbolSize:c.getItemVisual(t,"symbolSize"),fromSymbol:c.getItemVisual(t,"symbol"),toSymbolSize:d.getItemVisual(t,"symbolSize"),toSymbol:d.getItemVisual(t,"symbol")})}),u.updateData(f),h.line.eachItemGraphicEl(function(t,i){t.traverse(function(t){t.dataModel=e})}),u.__keep=!0,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markLine=t.markLine||{}}),UO.extend({type:"markArea",defaultOption:{zlevel:0,z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}}});var $O=function(t,e,i,n){var a=fx(t,n[0]),r=fx(t,n[1]),s=T,l=a.coord,u=r.coord;l[0]=s(l[0],-1/0),l[1]=s(l[1],-1/0),u[0]=s(u[0],1/0),u[1]=s(u[1],1/0);var h=o([{},a,r]);return h.coord=[a.coord,r.coord],h.x0=a.x,h.y0=a.y,h.x1=r.x,h.y1=r.y,h},JO=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]];qO.extend({type:"markArea",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markAreaModel;if(e){var n=e.getData();n.each(function(e){var o=f(JO,function(o){return Lx(n,e,o,t,i)});n.setItemLayout(e,o),n.getItemGraphicEl(e).setShape("points",o)})}},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(a)||l.set(a,{group:new tb});this.group.add(u.group),u.__keep=!0;var h=kx(o,t,e);e.setData(h),h.each(function(e){h.setItemLayout(e,f(JO,function(i){return Lx(h,e,i,t,n)})),h.setItemVisual(e,{color:s.getVisual("color")})}),h.diff(u.__data).add(function(t){var e=new pM({shape:{points:h.getItemLayout(t)}});h.setItemGraphicEl(t,e),u.group.add(e)}).update(function(t,i){var n=u.__data.getItemGraphicEl(i);Io(n,{shape:{points:h.getItemLayout(t)}},e,t),u.group.add(n),h.setItemGraphicEl(t,n)}).remove(function(t){var e=u.__data.getItemGraphicEl(t);u.group.remove(e)}).execute(),h.eachItemGraphicEl(function(t,i){var n=h.getItemModel(i),o=n.getModel("label"),a=n.getModel("emphasis.label"),s=h.getItemVisual(i,"color");t.useStyle(r(n.getModel("itemStyle").getItemStyle(),{fill:Yt(s,.4),stroke:s})),t.hoverStyle=n.getModel("emphasis.itemStyle").getItemStyle(),go(t.style,t.hoverStyle,o,a,{labelFetcher:e,labelDataIndex:i,defaultText:h.getName(i)||"",isRectText:!0,autoColor:s}),fo(t,{}),t.dataModel=e}),u.__data=h,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markArea=t.markArea||{}});lI.registerSubTypeDefaulter("timeline",function(){return"slider"}),Es({type:"timelineChange",event:"timelineChanged",update:"prepareAndUpdate"},function(t,e){var i=e.getComponent("timeline");return i&&null!=t.currentIndex&&(i.setCurrentIndex(t.currentIndex),!i.get("loop",!0)&&i.isIndexMax()&&i.setPlayState(!1)),e.resetOption("timeline"),r({currentIndex:i.option.currentIndex},t)}),Es({type:"timelinePlayChange",event:"timelinePlayChanged",update:"update"},function(t,e){var i=e.getComponent("timeline");i&&null!=t.playState&&i.setPlayState(t.playState)});var QO=lI.extend({type:"timeline",layoutMode:"box",defaultOption:{zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},init:function(t,e,i){this._data,this._names,this.mergeDefaultAndTheme(t,i),this._initData()},mergeOption:function(t){QO.superApply(this,"mergeOption",arguments),this._initData()},setCurrentIndex:function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(t>=e&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},getCurrentIndex:function(){return this.option.currentIndex},isIndexMax:function(){return this.getCurrentIndex()>=this._data.count()-1},setPlayState:function(t){this.option.autoPlay=!!t},getPlayState:function(){return!!this.option.autoPlay},_initData:function(){var t=this.option,e=t.data||[],n=t.axisType,o=this._names=[];if("category"===n){var a=[];d(e,function(t,e){var n,r=Li(t);w(t)?(n=i(t)).value=e:n=e,a.push(n),_(r)||null!=r&&!isNaN(r)||(r=""),o.push(r+"")}),e=a}var r={category:"ordinal",time:"time"}[n]||"number";(this._data=new vA([{name:"value",type:r}],this)).initData(e,o)},getData:function(){return this._data},getCategories:function(){if("category"===this.get("axisType"))return this._names.slice()}});h(QO.extend({type:"timeline.slider",defaultOption:{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"emptyCircle",symbolSize:10,lineStyle:{show:!0,width:2,color:"#304654"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#304654"},itemStyle:{color:"#304654",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:13,color:"#c23531",borderWidth:5,borderColor:"rgba(194,53,49, 0.5)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:22,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z",prevIcon:"path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z",color:"#304654",borderColor:"#304654",borderWidth:1},emphasis:{label:{show:!0,color:"#c23531"},itemStyle:{color:"#c23531"},controlStyle:{color:"#c23531",borderColor:"#c23531",borderWidth:2}},data:[]}}),ZI);var tE=qI.extend({type:"timeline"}),eE=function(t,e,i,n){aD.call(this,t,e,i),this.type=n||"value",this.model=null};eE.prototype={constructor:eE,getLabelModel:function(){return this.model.getModel("label")},isHorizontal:function(){return"horizontal"===this.model.get("orient")}},u(eE,aD);var iE=m,nE=d,oE=Math.PI;tE.extend({type:"timeline.slider",init:function(t,e){this.api=e,this._axis,this._viewRect,this._timer,this._currentPointer,this._mainGroup,this._labelGroup},render:function(t,e,i,n){if(this.model=t,this.api=i,this.ecModel=e,this.group.removeAll(),t.get("show",!0)){var o=this._layout(t,i),a=this._createGroup("mainGroup"),r=this._createGroup("labelGroup"),s=this._axis=this._createAxis(o,t);t.formatTooltip=function(t){return ia(s.scale.getLabel(t))},nE(["AxisLine","AxisTick","Control","CurrentPointer"],function(e){this["_render"+e](o,a,s,t)},this),this._renderAxisLabel(o,r,s,t),this._position(o,t)}this._doPlayStop()},remove:function(){this._clearTimer(),this.group.removeAll()},dispose:function(){this._clearTimer()},_layout:function(t,e){var i=t.get("label.position"),n=t.get("orient"),o=Ex(t,e);null==i||"auto"===i?i="horizontal"===n?o.y+o.height/2=0||"+"===i?"left":"right"},r={horizontal:i>=0||"+"===i?"top":"bottom",vertical:"middle"},s={horizontal:0,vertical:oE/2},l="vertical"===n?o.height:o.width,u=t.getModel("controlStyle"),h=u.get("show",!0),c=h?u.get("itemSize"):0,d=h?u.get("itemGap"):0,f=c+d,p=t.get("label.rotate")||0;p=p*oE/180;var g,m,v,y,x=u.get("position",!0),_=h&&u.get("showPlayBtn",!0),w=h&&u.get("showPrevBtn",!0),b=h&&u.get("showNextBtn",!0),S=0,M=l;return"left"===x||"bottom"===x?(_&&(g=[0,0],S+=f),w&&(m=[S,0],S+=f),b&&(v=[M-c,0],M-=f)):(_&&(g=[M-c,0],M-=f),w&&(m=[0,0],S+=f),b&&(v=[M-c,0],M-=f)),y=[S,M],t.get("inverse")&&y.reverse(),{viewRect:o,mainLength:l,orient:n,rotation:s[n],labelRotation:p,labelPosOpt:i,labelAlign:t.get("label.align")||a[n],labelBaseline:t.get("label.verticalAlign")||t.get("label.baseline")||r[n],playPosition:g,prevBtnPosition:m,nextBtnPosition:v,axisExtent:y,controlSize:c,controlGap:d}},_position:function(t,e){function i(t){var e=t.position;t.origin=[c[0][0]-e[0],c[1][0]-e[1]]}function n(t){return[[t.x,t.x+t.width],[t.y,t.y+t.height]]}function o(t,e,i,n,o){t[n]+=i[n][o]-e[n][o]}var a=this._mainGroup,r=this._labelGroup,s=t.viewRect;if("vertical"===t.orient){var l=xt(),u=s.x,h=s.y+s.height;St(l,l,[-u,-h]),Mt(l,l,-oE/2),St(l,l,[u,h]),(s=s.clone()).applyTransform(l)}var c=n(s),d=n(a.getBoundingRect()),f=n(r.getBoundingRect()),p=a.position,g=r.position;g[0]=p[0]=c[0][0];var m=t.labelPosOpt;if(isNaN(m))o(p,d,c,1,v="+"===m?0:1),o(g,f,c,1,1-v);else{var v=m>=0?0:1;o(p,d,c,1,v),g[1]=p[1]+m}a.attr("position",p),r.attr("position",g),a.rotation=r.rotation=t.rotation,i(a),i(r)},_createAxis:function(t,e){var i=e.getData(),n=e.get("axisType"),o=Hl(e,n);o.getTicks=function(){return i.mapArray(["value"],function(t){return t})};var a=i.getDataExtent("value");o.setExtent(a[0],a[1]),o.niceTicks();var r=new eE("value",o,t.axisExtent,n);return r.model=e,r},_createGroup:function(t){var e=this["_"+t]=new tb;return this.group.add(e),e},_renderAxisLine:function(t,e,i,n){var o=i.getExtent();n.get("lineStyle.show")&&e.add(new _M({shape:{x1:o[0],y1:0,x2:o[1],y2:0},style:a({lineCap:"round"},n.getModel("lineStyle").getLineStyle()),silent:!0,z2:1}))},_renderAxisTick:function(t,e,i,n){var o=n.getData(),a=i.scale.getTicks();nE(a,function(t){var a=i.dataToCoord(t),r=o.getItemModel(t),s=r.getModel("itemStyle"),l=r.getModel("emphasis.itemStyle"),u={position:[a,0],onclick:iE(this._changeTimeline,this,t)},h=zx(r,s,e,u);fo(h,l.getItemStyle()),r.get("tooltip")?(h.dataIndex=t,h.dataModel=n):h.dataIndex=h.dataModel=null},this)},_renderAxisLabel:function(t,e,i,n){if(i.getLabelModel().get("show")){var o=n.getData(),a=i.getViewLabels();nE(a,function(n){var a=n.tickValue,r=o.getItemModel(a),s=r.getModel("label"),l=r.getModel("emphasis.label"),u=i.dataToCoord(n.tickValue),h=new rM({position:[u,0],rotation:t.labelRotation-t.rotation,onclick:iE(this._changeTimeline,this,a),silent:!1});mo(h.style,s,{text:n.formattedLabel,textAlign:t.labelAlign,textVerticalAlign:t.labelBaseline}),e.add(h),fo(h,mo({},l))},this)}},_renderControl:function(t,e,i,n){function o(t,i,o,h){if(t){var c=Rx(n,i,u,{position:t,origin:[a/2,0],rotation:h?-r:0,rectHover:!0,style:s,onclick:o});e.add(c),fo(c,l)}}var a=t.controlSize,r=t.rotation,s=n.getModel("controlStyle").getItemStyle(),l=n.getModel("emphasis.controlStyle").getItemStyle(),u=[0,-a/2,a,a],h=n.getPlayState(),c=n.get("inverse",!0);o(t.nextBtnPosition,"controlStyle.nextIcon",iE(this._changeTimeline,this,c?"-":"+")),o(t.prevBtnPosition,"controlStyle.prevIcon",iE(this._changeTimeline,this,c?"+":"-")),o(t.playPosition,"controlStyle."+(h?"stopIcon":"playIcon"),iE(this._handlePlayClick,this,!h),!0)},_renderCurrentPointer:function(t,e,i,n){var o=n.getData(),a=n.getCurrentIndex(),r=o.getItemModel(a).getModel("checkpointStyle"),s=this,l={onCreate:function(t){t.draggable=!0,t.drift=iE(s._handlePointerDrag,s),t.ondragend=iE(s._handlePointerDragend,s),Bx(t,a,i,n,!0)},onUpdate:function(t){Bx(t,a,i,n)}};this._currentPointer=zx(r,r,this._mainGroup,{},this._currentPointer,l)},_handlePlayClick:function(t){this._clearTimer(),this.api.dispatchAction({type:"timelinePlayChange",playState:t,from:this.uid})},_handlePointerDrag:function(t,e,i){this._clearTimer(),this._pointerChangeTimeline([i.offsetX,i.offsetY])},_handlePointerDragend:function(t){this._pointerChangeTimeline([t.offsetX,t.offsetY],!0)},_pointerChangeTimeline:function(t,e){var i=this._toAxisCoord(t)[0],n=Fo(this._axis.getExtent().slice());i>n[1]&&(i=n[1]),ii.getHeight()&&(n.textPosition="top",l=!0);var u=l?-5-o.height:s+8;a+o.width/2>i.getWidth()?(n.textPosition=["100%",u],n.textAlign="right"):a-o.width/2<0&&(n.textPosition=[0,u],n.textAlign="left")}})}},updateView:function(t,e,i,n){d(this._features,function(t){t.updateView&&t.updateView(t.model,e,i,n)})},remove:function(t,e){d(this._features,function(i){i.remove&&i.remove(t,e)}),this.group.removeAll()},dispose:function(t,e){d(this._features,function(i){i.dispose&&i.dispose(t,e)})}});var rE=rT.toolbox.saveAsImage;Gx.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:rE.title,type:"png",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:rE.lang.slice()},Gx.prototype.unusable=!U_.canvasSupported,Gx.prototype.onclick=function(t,e){var i=this.model,n=i.get("name")||t.get("title.0.text")||"echarts",o=document.createElement("a"),a=i.get("type",!0)||"png";o.download=n+"."+a,o.target="_blank";var r=e.getConnectedDataURL({type:a,backgroundColor:i.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",excludeComponents:i.get("excludeComponents"),pixelRatio:i.get("pixelRatio")});if(o.href=r,"function"!=typeof MouseEvent||U_.browser.ie||U_.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var s=atob(r.split(",")[1]),l=s.length,u=new Uint8Array(l);l--;)u[l]=s.charCodeAt(l);var h=new Blob([u]);window.navigator.msSaveOrOpenBlob(h,n+"."+a)}else{var c=i.get("lang"),d='';window.open().document.write(d)}else{var f=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});o.dispatchEvent(f)}},Ty("saveAsImage",Gx);var sE=rT.toolbox.magicType;Fx.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z",tiled:"M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z"},title:i(sE.title),option:{},seriesIndex:{}};var lE=Fx.prototype;lE.getIcons=function(){var t=this.model,e=t.get("icon"),i={};return d(t.get("type"),function(t){e[t]&&(i[t]=e[t])}),i};var uE={line:function(t,e,i,o){if("bar"===t)return n({id:e,type:"line",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.line")||{},!0)},bar:function(t,e,i,o){if("line"===t)return n({id:e,type:"bar",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.bar")||{},!0)},stack:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:"__ec_magicType_stack__"},o.get("option.stack")||{},!0)},tiled:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:""},o.get("option.tiled")||{},!0)}},hE=[["line","bar"],["stack","tiled"]];lE.onclick=function(t,e,i){var n=this.model,o=n.get("seriesIndex."+i);if(uE[i]){var a={series:[]};d(hE,function(t){l(t,i)>=0&&d(t,function(t){n.setIconStatus(t,"normal")})}),n.setIconStatus(i,"emphasis"),t.eachComponent({mainType:"series",query:null==o?null:{seriesIndex:o}},function(e){var o=e.subType,s=e.id,l=uE[i](o,s,e,n);l&&(r(l,e.option),a.series.push(l));var u=e.coordinateSystem;if(u&&"cartesian2d"===u.type&&("line"===i||"bar"===i)){var h=u.getAxesByScale("ordinal")[0];if(h){var c=h.dim+"Axis",d=t.queryComponents({mainType:c,index:e.get(name+"Index"),id:e.get(name+"Id")})[0].componentIndex;a[c]=a[c]||[];for(var f=0;f<=d;f++)a[c][d]=a[c][d]||{};a[c][d].boundaryGap="bar"===i}}}),e.dispatchAction({type:"changeMagicType",currentType:i,newOption:a})}},Es({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),Ty("magicType",Fx);var cE=rT.toolbox.dataView,dE=new Array(60).join("-"),fE="\t",pE=new RegExp("["+fE+"]+","g");$x.defaultOption={show:!0,readOnly:!1,optionToContent:null,contentToOption:null,icon:"M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28",title:i(cE.title),lang:i(cE.lang),backgroundColor:"#fff",textColor:"#000",textareaColor:"#fff",textareaBorderColor:"#333",buttonColor:"#c23531",buttonTextColor:"#fff"},$x.prototype.onclick=function(t,e){function i(){n.removeChild(a),x._dom=null}var n=e.getDom(),o=this.model;this._dom&&n.removeChild(this._dom);var a=document.createElement("div");a.style.cssText="position:absolute;left:5px;top:5px;bottom:5px;right:5px;",a.style.backgroundColor=o.get("backgroundColor")||"#fff";var r=document.createElement("h4"),s=o.get("lang")||[];r.innerHTML=s[0]||o.get("title"),r.style.cssText="margin: 10px 20px;",r.style.color=o.get("textColor");var l=document.createElement("div"),u=document.createElement("textarea");l.style.cssText="display:block;width:100%;overflow:auto;";var h=o.get("optionToContent"),c=o.get("contentToOption"),d=Ux(t);if("function"==typeof h){var f=h(e.getOption());"string"==typeof f?l.innerHTML=f:M(f)&&l.appendChild(f)}else l.appendChild(u),u.readOnly=o.get("readOnly"),u.style.cssText="width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;",u.style.color=o.get("textColor"),u.style.borderColor=o.get("textareaBorderColor"),u.style.backgroundColor=o.get("textareaColor"),u.value=d.value;var p=d.meta,g=document.createElement("div");g.style.cssText="position:absolute;bottom:0;left:0;right:0;";var m="float:right;margin-right:20px;border:none;cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px",v=document.createElement("div"),y=document.createElement("div");m+=";background-color:"+o.get("buttonColor"),m+=";color:"+o.get("buttonTextColor");var x=this;ht(v,"click",i),ht(y,"click",function(){var t;try{t="function"==typeof c?c(l,e.getOption()):Kx(u.value,p)}catch(t){throw i(),new Error("Data view format error "+t)}t&&e.dispatchAction({type:"changeDataView",newOption:t}),i()}),v.innerHTML=s[1],y.innerHTML=s[2],y.style.cssText=m,v.style.cssText=m,!o.get("readOnly")&&g.appendChild(y),g.appendChild(v),ht(u,"keydown",function(t){if(9===(t.keyCode||t.which)){var e=this.value,i=this.selectionStart,n=this.selectionEnd;this.value=e.substring(0,i)+fE+e.substring(n),this.selectionStart=this.selectionEnd=i+1,mw(t)}}),a.appendChild(r),a.appendChild(l),a.appendChild(g),l.style.height=n.clientHeight-80+"px",n.appendChild(a),this._dom=a},$x.prototype.remove=function(t,e){this._dom&&e.getDom().removeChild(this._dom)},$x.prototype.dispose=function(t,e){this.remove(t,e)},Ty("dataView",$x),Es({type:"changeDataView",event:"dataViewChanged",update:"prepareAndUpdate"},function(t,e){var i=[];d(t.newOption.series,function(t){var n=e.getSeriesByName(t.name)[0];if(n){var o=n.get("data");i.push({name:t.name,data:Jx(t.data,o)})}else i.push(a({type:"scatter"},t))}),e.mergeOption(r({series:i},t.newOption))});var gE=d,mE="\0_ec_hist_store";iO.extend({type:"dataZoom.select"}),nO.extend({type:"dataZoom.select"});var vE=rT.toolbox.dataZoom,yE=d,xE="\0_ec_\0toolbox-dataZoom_";o_.defaultOption={show:!0,icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:i(vE.title)};var _E=o_.prototype;_E.render=function(t,e,i,n){this.model=t,this.ecModel=e,this.api=i,s_(t,e,this,n,i),r_(t,e)},_E.onclick=function(t,e,i){wE[i].call(this)},_E.remove=function(t,e){this._brushController.unmount()},_E.dispose=function(t,e){this._brushController.dispose()};var wE={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(t_(this.ecModel))}};_E._onBrush=function(t,e){function i(t,e,i){var r=e.getAxis(t),s=r.model,l=n(t,s,a),u=l.findRepresentativeAxisProxy(s).getMinMaxSpan();null==u.minValueSpan&&null==u.maxValueSpan||(i=QL(0,i.slice(),r.scale.getExtent(),0,u.minValueSpan,u.maxValueSpan)),l&&(o[l.id]={dataZoomId:l.id,startValue:i[0],endValue:i[1]})}function n(t,e,i){var n;return i.eachComponent({mainType:"dataZoom",subType:"select"},function(i){i.getAxisModel(t,e.componentIndex)&&(n=i)}),n}if(e.isEnd&&t.length){var o={},a=this.ecModel;this._brushController.updateCovers([]),new hy(a_(this.model.option),a,{include:["grid"]}).matchOutputRanges(t,a,function(t,e,n){if("cartesian2d"===n.type){var o=t.brushType;"rect"===o?(i("x",n,e[0]),i("y",n,e[1])):i({lineX:"x",lineY:"y"}[o],n,e)}}),Qx(a,o),this._dispatchZoomAction(o)}},_E._dispatchZoomAction=function(t){var e=[];yE(t,function(t,n){e.push(i(t))}),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},Ty("dataZoom",o_),Ns(function(t){function e(t,e){if(e){var o=t+"Index",a=e[o];null==a||"all"===a||y(a)||(a=!1===a||"none"===a?[]:[a]),i(t,function(e,i){if(null==a||"all"===a||-1!==l(a,i)){var r={type:"select",$fromToolbox:!0,id:xE+t+i};r[o]=i,n.push(r)}})}}function i(e,i){var n=t[e];y(n)||(n=n?[n]:[]),yE(n,i)}if(t){var n=t.dataZoom||(t.dataZoom=[]);y(n)||(t.dataZoom=n=[n]);var o=t.toolbox;if(o&&(y(o)&&(o=o[0]),o&&o.feature)){var a=o.feature.dataZoom;e("xAxis",a),e("yAxis",a)}}});var bE=rT.toolbox.restore;l_.defaultOption={show:!0,icon:"M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5",title:bE.title},l_.prototype.onclick=function(t,e,i){e_(t),e.dispatchAction({type:"restore",from:this.uid})},Ty("restore",l_),Es({type:"restore",event:"restore",update:"prepareAndUpdate"},function(t,e){e.resetOption("recreate")});var SE,ME="urn:schemas-microsoft-com:vml",IE="undefined"==typeof window?null:window,TE=!1,AE=IE&&IE.document;if(AE&&!U_.canvasSupported)try{!AE.namespaces.zrvml&&AE.namespaces.add("zrvml",ME),SE=function(t){return AE.createElement("')}}catch(t){SE=function(t){return AE.createElement("<"+t+' xmlns="'+ME+'" class="zrvml">')}}var DE=ES.CMD,CE=Math.round,LE=Math.sqrt,kE=Math.abs,PE=Math.cos,NE=Math.sin,OE=Math.max;if(!U_.canvasSupported){var EE=21600,RE=EE/2,zE=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=EE+","+EE,t.coordorigin="0,0"},BE=function(t){return String(t).replace(/&/g,"&").replace(/"/g,""")},VE=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},GE=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},FE=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},WE=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},HE=function(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t},ZE=function(t,e,i){var n=Gt(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=VE(n[0],n[1],n[2]),t.opacity=i*n[3])},UE=function(t){var e=Gt(t);return[VE(e[0],e[1],e[2]),e[3]]},XE=function(t,e,i){var n=e.fill;if(null!=n)if(n instanceof IM){var o,a=0,r=[0,0],s=0,l=1,u=i.getBoundingRect(),h=u.width,c=u.height;if("linear"===n.type){o="gradient";var d=i.transform,f=[n.x*h,n.y*c],p=[n.x2*h,n.y2*c];d&&(Q(f,f,d),Q(p,p,d));var g=p[0]-f[0],m=p[1]-f[1];(a=180*Math.atan2(g,m)/Math.PI)<0&&(a+=360),a<1e-6&&(a=0)}else{o="gradientradial";var f=[n.x*h,n.y*c],d=i.transform,v=i.scale,y=h,x=c;r=[(f[0]-u.x)/y,(f[1]-u.y)/x],d&&Q(f,f,d),y/=v[0]*EE,x/=v[1]*EE;var _=OE(y,x);s=0/_,l=2*n.r/_-s}var w=n.colorStops.slice();w.sort(function(t,e){return t.offset-e.offset});for(var b=w.length,S=[],M=[],I=0;I=2){var D=S[0][0],C=S[1][0],L=S[0][1]*e.opacity,k=S[1][1]*e.opacity;t.type=o,t.method="none",t.focus="100%",t.angle=a,t.color=D,t.color2=C,t.colors=M.join(","),t.opacity=k,t.opacity2=L}"radial"===o&&(t.focusposition=r.join(","))}else ZE(t,n,e.opacity)},jE=function(t,e){null!=e.lineDash&&(t.dashstyle=e.lineDash.join(" ")),null==e.stroke||e.stroke instanceof IM||ZE(t,e.stroke,e.opacity)},YE=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof IM&&FE(t,a),a||(a=u_(e)),o?XE(a,i,n):jE(a,i),GE(t,a)):(t[o?"filled":"stroked"]="false",FE(t,a))},qE=[[],[],[]],KE=function(t,e){var i,n,o,a,r,s,l=DE.M,u=DE.C,h=DE.L,c=DE.A,d=DE.Q,f=[],p=t.data,g=t.len();for(a=0;a.01?N&&(O+=.0125):Math.abs(E-D)<1e-4?N&&OA?x-=.0125:x+=.0125:N&&ED?y+=.0125:y-=.0125),f.push(R,CE(((A-C)*M+b)*EE-RE),",",CE(((D-L)*I+S)*EE-RE),",",CE(((A+C)*M+b)*EE-RE),",",CE(((D+L)*I+S)*EE-RE),",",CE((O*M+b)*EE-RE),",",CE((E*I+S)*EE-RE),",",CE((y*M+b)*EE-RE),",",CE((x*I+S)*EE-RE)),r=y,s=x;break;case DE.R:var z=qE[0],B=qE[1];z[0]=p[a++],z[1]=p[a++],B[0]=z[0]+p[a++],B[1]=z[1]+p[a++],e&&(Q(z,z,e),Q(B,B,e)),z[0]=CE(z[0]*EE-RE),B[0]=CE(B[0]*EE-RE),z[1]=CE(z[1]*EE-RE),B[1]=CE(B[1]*EE-RE),f.push(" m ",z[0],",",z[1]," l ",B[0],",",z[1]," l ",B[0],",",B[1]," l ",z[0],",",B[1]);break;case DE.Z:f.push(" x ")}if(i>0){f.push(n);for(var V=0;V100&&(tR=0,QE={});var i,n=eR.style;try{n.font=t,i=n.fontFamily.split(",")[0]}catch(t){}e={style:n.fontStyle||"normal",variant:n.fontVariant||"normal",weight:n.fontWeight||"normal",size:0|parseFloat(n.fontSize||12),family:i||"Microsoft YaHei"},QE[t]=e,tR++}return e};!function(t,e){bb[t]=e}("measureText",function(t,e){var i=AE;JE||((JE=i.createElement("div")).style.cssText="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;",AE.body.appendChild(JE));try{JE.style.font=e}catch(t){}return JE.innerHTML="",JE.appendChild(i.createTextNode(t)),{width:JE.offsetWidth}});for(var nR=new de,oR=[Db,di,fi,Pn,rM],aR=0;aR=o&&u+1>=a){for(var h=[],c=0;c=o&&c+1>=a)return T_(0,s.components);l[i]=s}else l[i]=void 0}r++}();if(d)return d}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},D_.prototype.update=function(t,e){if(t){var i=this.getDefs(!1);if(t[this._domName]&&i.contains(t[this._domName]))"function"==typeof e&&e(t);else{var n=this.add(t);n&&(t[this._domName]=n)}}},D_.prototype.addDom=function(t){this.getDefs(!0).appendChild(t)},D_.prototype.removeDom=function(t){var e=this.getDefs(!1);e&&t[this._domName]&&(e.removeChild(t[this._domName]),t[this._domName]=null)},D_.prototype.getDoms=function(){var t=this.getDefs(!1);if(!t)return[];var e=[];return d(this._tagNames,function(i){var n=t.getElementsByTagName(i);e=e.concat([].slice.call(n))}),e},D_.prototype.markAllUnused=function(){var t=this;d(this.getDoms(),function(e){e[t._markLabel]="0"})},D_.prototype.markUsed=function(t){t&&(t[this._markLabel]="1")},D_.prototype.removeUnused=function(){var t=this.getDefs(!1);if(t){var e=this;d(this.getDoms(),function(i){"1"!==i[e._markLabel]&&t.removeChild(i)})}},D_.prototype.getSvgProxy=function(t){return t instanceof Pn?yR:t instanceof fi?xR:t instanceof rM?_R:yR},D_.prototype.getTextSvgElement=function(t){return t.__textSvgEl},D_.prototype.getSvgElement=function(t){return t.__svgEl},u(C_,D_),C_.prototype.addWithoutUpdate=function(t,e){if(e&&e.style){var i=this;d(["fill","stroke"],function(n){if(e.style[n]&&("linear"===e.style[n].type||"radial"===e.style[n].type)){var o,a=e.style[n],r=i.getDefs(!0);a._dom?(o=a._dom,r.contains(a._dom)||i.addDom(o)):o=i.add(a),i.markUsed(e);var s=o.getAttribute("id");t.setAttribute(n,"url(#"+s+")")}})}},C_.prototype.add=function(t){var e;if("linear"===t.type)e=this.createElement("linearGradient");else{if("radial"!==t.type)return Yw("Illegal gradient type."),null;e=this.createElement("radialGradient")}return t.id=t.id||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-gradient-"+t.id),this.updateDom(t,e),this.addDom(e),e},C_.prototype.update=function(t){var e=this;D_.prototype.update.call(this,t,function(){var i=t.type,n=t._dom.tagName;"linear"===i&&"linearGradient"===n||"radial"===i&&"radialGradient"===n?e.updateDom(t,t._dom):(e.removeDom(t),e.add(t))})},C_.prototype.updateDom=function(t,e){if("linear"===t.type)e.setAttribute("x1",t.x),e.setAttribute("y1",t.y),e.setAttribute("x2",t.x2),e.setAttribute("y2",t.y2);else{if("radial"!==t.type)return void Yw("Illegal gradient type.");e.setAttribute("cx",t.x),e.setAttribute("cy",t.y),e.setAttribute("r",t.r)}t.global?e.setAttribute("gradientUnits","userSpaceOnUse"):e.setAttribute("gradientUnits","objectBoundingBox"),e.innerHTML="";for(var i=t.colorStops,n=0,o=i.length;n0){var n,o,a=this.getDefs(!0),r=e[0],s=i?"_textDom":"_dom";r[s]?(o=r[s].getAttribute("id"),n=r[s],a.contains(n)||a.appendChild(n)):(o="zr"+this._zrId+"-clip-"+this.nextId,++this.nextId,(n=this.createElement("clipPath")).setAttribute("id",o),a.appendChild(n),r[s]=n);var l=this.getSvgProxy(r);if(r.transform&&r.parent.invTransform&&!i){var u=Array.prototype.slice.call(r.transform);bt(r.transform,r.parent.invTransform,r.transform),l.brush(r),r.transform=u}else l.brush(r);var h=this.getSvgElement(r);n.innerHTML="",n.appendChild(h.cloneNode()),t.setAttribute("clip-path","url(#"+o+")"),e.length>1&&this.updateDom(n,e.slice(1),i)}else t&&t.setAttribute("clip-path","none")},L_.prototype.markUsed=function(t){var e=this;t.__clipPaths&&t.__clipPaths.length>0&&d(t.__clipPaths,function(t){t._dom&&D_.prototype.markUsed.call(e,t._dom),t._textDom&&D_.prototype.markUsed.call(e,t._textDom)})},u(k_,D_),k_.prototype.addWithoutUpdate=function(t,e){if(e&&P_(e.style)){var i,n=e.style;n._shadowDom?(i=n._shadowDom,this.getDefs(!0).contains(n._shadowDom)||this.addDom(i)):i=this.add(e),this.markUsed(e);var o=i.getAttribute("id");t.style.filter="url(#"+o+")"}},k_.prototype.add=function(t){var e=this.createElement("filter"),i=t.style;return i._shadowDomId=i._shadowDomId||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-shadow-"+i._shadowDomId),this.updateDom(t,e),this.addDom(e),e},k_.prototype.update=function(t,e){var i=e.style;if(P_(i)){var n=this;D_.prototype.update.call(this,e,function(t){n.updateDom(e,t._shadowDom)})}else this.remove(t,i)},k_.prototype.remove=function(t,e){null!=e._shadowDomId&&(this.removeDom(e),t.style.filter="")},k_.prototype.updateDom=function(t,e){var i=e.getElementsByTagName("feDropShadow");i=0===i.length?this.createElement("feDropShadow"):i[0];var n,o,a,r,s=t.style,l=t.scale?t.scale[0]||1:1,u=t.scale?t.scale[1]||1:1;if(s.shadowBlur||s.shadowOffsetX||s.shadowOffsetY)n=s.shadowOffsetX||0,o=s.shadowOffsetY||0,a=s.shadowBlur,r=s.shadowColor;else{if(!s.textShadowBlur)return void this.removeDom(e,s);n=s.textShadowOffsetX||0,o=s.textShadowOffsetY||0,a=s.textShadowBlur,r=s.textShadowColor}i.setAttribute("dx",n/l),i.setAttribute("dy",o/u),i.setAttribute("flood-color",r);var h=a/2/l+" "+a/2/u;i.setAttribute("stdDeviation",h),e.setAttribute("x","-100%"),e.setAttribute("y","-100%"),e.setAttribute("width",Math.ceil(a/2*200)+"%"),e.setAttribute("height",Math.ceil(a/2*200)+"%"),e.appendChild(i),s._shadowDom=e},k_.prototype.markUsed=function(t){var e=t.style;e&&e._shadowDom&&D_.prototype.markUsed.call(this,e._shadowDom)};var IR=function(t,e,i,n){this.root=t,this.storage=e,this._opts=i=a({},i||{});var o=p_("svg");o.setAttribute("xmlns","http://www.w3.org/2000/svg"),o.setAttribute("version","1.1"),o.setAttribute("baseProfile","full"),o.style.cssText="user-select:none;position:absolute;left:0;top:0;",this.gradientManager=new C_(n,o),this.clipPathManager=new L_(n,o),this.shadowManager=new k_(n,o);var r=document.createElement("div");r.style.cssText="overflow:hidden;position:relative",this._svgRoot=o,this._viewport=r,t.appendChild(r),r.appendChild(o),this.resize(i.width,i.height),this._visibleList=[]};IR.prototype={constructor:IR,getType:function(){return"svg"},getViewportRoot:function(){return this._viewport},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(){var t=this.storage.getDisplayList(!0);this._paintList(t)},setBackgroundColor:function(t){this._viewport.style.background=t},_paintList:function(t){this.gradientManager.markAllUnused(),this.clipPathManager.markAllUnused(),this.shadowManager.markAllUnused();var e,i=this._svgRoot,n=this._visibleList,o=t.length,a=[];for(e=0;e=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},resize:function(t,e){var i=this._viewport;i.style.display="none";var n=this._opts;if(null!=t&&(n.width=t),null!=e&&(n.height=e),t=this._getSize(0),e=this._getSize(1),i.style.display="",this._width!==t||this._height!==e){this._width=t,this._height=e;var o=i.style;o.width=t+"px",o.height=e+"px";var a=this._svgRoot;a.setAttribute("width",t),a.setAttribute("height",e)}},getWidth:function(){return this._width},getHeight:function(){return this._height},_getSize:function(t){var e=this._opts,i=["width","height"][t],n=["clientWidth","clientHeight"][t],o=["paddingLeft","paddingTop"][t],a=["paddingRight","paddingBottom"][t];if(null!=e[i]&&"auto"!==e[i])return parseFloat(e[i]);var r=this.root,s=document.defaultView.getComputedStyle(r);return(r[n]||N_(s[i])||N_(r.style[i]))-(N_(s[o])||0)-(N_(s[a])||0)|0},dispose:function(){this.root.innerHTML="",this._svgRoot=this._viewport=this.storage=null},clear:function(){this._viewport&&this.root.removeChild(this._viewport)},pathToDataUrl:function(){return this.refresh(),"data:image/svg+xml;charset=UTF-8,"+this._svgRoot.outerHTML}},d(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","toDataURL","pathToImage"],function(t){IR.prototype[t]=F_(t)}),Ti("svg",IR),t.version="4.2.1",t.dependencies=ET,t.PRIORITY=VT,t.init=function(t,e,i){var n=ks(t);if(n)return n;var o=new us(t,e,i);return o.id="ec_"+iA++,tA[o.id]=o,Fi(t,oA,o.id),Cs(o),o},t.connect=function(t){if(y(t)){var e=t;t=null,kT(e,function(e){null!=e.group&&(t=e.group)}),t=t||"g_"+nA++,kT(e,function(e){e.group=t})}return eA[t]=!0,t},t.disConnect=Ls,t.disconnect=aA,t.dispose=function(t){"string"==typeof t?t=tA[t]:t instanceof us||(t=ks(t)),t instanceof us&&!t.isDisposed()&&t.dispose()},t.getInstanceByDom=ks,t.getInstanceById=function(t){return tA[t]},t.registerTheme=Ps,t.registerPreprocessor=Ns,t.registerProcessor=Os,t.registerPostUpdate=function(t){KT.push(t)},t.registerAction=Es,t.registerCoordinateSystem=Rs,t.getCoordinateSystemDimensions=function(t){var e=Fa.get(t);if(e)return e.getDimensionsInfo?e.getDimensionsInfo():e.dimensions.slice()},t.registerLayout=zs,t.registerVisual=Bs,t.registerLoading=Gs,t.extendComponentModel=Fs,t.extendComponentView=Ws,t.extendSeriesModel=Hs,t.extendChartView=Zs,t.setCanvasCreator=function(t){e("createCanvas",t)},t.registerMap=function(t,e,i){DT.registerMap(t,e,i)},t.getMap=function(t){var e=DT.retrieveMap(t);return e&&e[0]&&{geoJson:e[0].geoJSON,specialAreas:e[0].specialAreas}},t.dataTool=rA,t.zrender=Hb,t.number=YM,t.format=eI,t.throttle=Pr,t.helper=tD,t.matrix=Sw,t.vector=cw,t.color=Ww,t.parseGeoJSON=iD,t.parseGeoJson=rD,t.util=sD,t.graphic=lD,t.List=vA,t.Model=No,t.Axis=aD,t.env=U_}); \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/select-lay/changelog.md b/yanzhu-ui-app/uni_modules/select-lay/changelog.md new file mode 100644 index 00000000..0dc15c03 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/select-lay/changelog.md @@ -0,0 +1,10 @@ +## 1.3.8(2022-01-18) +修复了一些小问题,应该...没问题了吧。。。 +## 1.3.7(2022-01-14) +修复了个bug,该bug导致:手机端使用时,当获取焦点方式展开列表,列表无法滑动 +## 1.3.6(2021-09-22) +修改了插件部分内部元素,防止该组件在app端时,滑动穿透。 +## 1.3.5(2021-09-22) +【禁用组件】提示更明显了。新增了【正在搜索...】提示。添加了事件修饰.stop ,不知道是否能解决有事件穿透行为的bug。ps:我还没遇到这个问题,烦! +## 1.3.4(2021-09-10) +修改插件为uni_modules目录结构 diff --git a/yanzhu-ui-app/uni_modules/select-lay/components/select-lay/select-lay.vue b/yanzhu-ui-app/uni_modules/select-lay/components/select-lay/select-lay.vue new file mode 100644 index 00000000..0340a139 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/select-lay/components/select-lay/select-lay.vue @@ -0,0 +1,432 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/select-lay/package.json b/yanzhu-ui-app/uni_modules/select-lay/package.json new file mode 100644 index 00000000..7e402fed --- /dev/null +++ b/yanzhu-ui-app/uni_modules/select-lay/package.json @@ -0,0 +1,80 @@ +{ + "id": "select-lay", + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "" + }, + "displayName": "select-lay", + "version": "1.3.8", + "description": "简单的下拉选择插件", + "keywords": [ + "select", + "下拉", + "选择" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.0.7" + }, + "uni_modules": { + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "u" + }, + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "u", + "Edge": "u", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/select-lay/readme.md b/yanzhu-ui-app/uni_modules/select-lay/readme.md new file mode 100644 index 00000000..f38b6c7c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/select-lay/readme.md @@ -0,0 +1,173 @@ +## 插件使用方法: + + `` + +## 配置参数: + + 属性名|类型|默认值|说明 + :--:|:--:|:--:|- + value|String|""|默认展示的value值 + name|String|""|input的字段名 + zindex|Number|""|层级,默认999,防止多个组件一起使用时下拉栏穿透 + slabel|String|label|自定义列表中键值对关系,参考示例 + svalue|String|value|自定义列表中键值对关系,该值对应value,参考示例 + placeholder|String|请选择|无选项时展示的文字 + showplaceholder|Boolean|true|下拉时是否展示请选择按钮 + options|Array|无|数据列表 + disabled|Boolean|false|是否禁用 + +## 事件: + + 事件名|说明|返回值 + :--:|:--:|- + @selectitem|点击项目触发的事件|参数 (索引,具体项目) + +## 说明: + + 此插件依赖scss,请务必安装!!! + + +## 示例: + + ``` + + + + + ``` + \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-badge/changelog.md b/yanzhu-ui-app/uni_modules/uni-badge/changelog.md new file mode 100644 index 00000000..e352c60c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-badge/changelog.md @@ -0,0 +1,33 @@ +## 1.2.2(2023-01-28) +- 修复 运行/打包 控制台警告问题 +## 1.2.1(2022-09-05) +- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473) +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge) +## 1.1.7(2021-11-08) +- 优化 升级ui +- 修改 size 属性默认值调整为 small +- 修改 type 属性,默认值调整为 error,info 替换 default +## 1.1.6(2021-09-22) +- 修复 在字节小程序上样式不生效的 bug +## 1.1.5(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.4(2021-07-29) +- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性 +## 1.1.3(2021-06-24) +- 优化 示例项目 +## 1.1.1(2021-05-12) +- 新增 组件示例地址 +## 1.1.0(2021-05-12) +- 新增 uni-badge 的 absolute 属性,支持定位 +- 新增 uni-badge 的 offset 属性,支持定位偏移 +- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 +- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ +- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 +## 1.0.7(2021-05-07) +- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug +- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug +- 新增 uni-badge 属性 custom-style, 支持自定义样式 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/yanzhu-ui-app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue new file mode 100644 index 00000000..956354b4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-badge/package.json b/yanzhu-ui-app/uni_modules/uni-badge/package.json new file mode 100644 index 00000000..b0bac937 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-badge/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-badge", + "displayName": "uni-badge 数字角标", + "version": "1.2.2", + "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", + "keywords": [ + "", + "badge", + "uni-ui", + "uniui", + "数字角标", + "徽章" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-badge/readme.md b/yanzhu-ui-app/uni_modules/uni-badge/readme.md new file mode 100644 index 00000000..bdf175da --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-badge/readme.md @@ -0,0 +1,10 @@ +## Badge 数字角标 +> **组件名:uni-badge** +> 代码块: `uBadge` + +数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-breadcrumb/changelog.md b/yanzhu-ui-app/uni_modules/uni-breadcrumb/changelog.md new file mode 100644 index 00000000..209e5c5f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-breadcrumb/changelog.md @@ -0,0 +1,6 @@ +## 0.1.2(2022-06-08) +- 修复 微信小程序 separator 不显示的Bug +## 0.1.1(2022-06-02) +- 新增 支持 uni.scss 修改颜色 +## 0.1.0(2022-04-21) +- 初始化 diff --git a/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue b/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue new file mode 100644 index 00000000..b9edbd62 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue @@ -0,0 +1,121 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue b/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue new file mode 100644 index 00000000..94493a21 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue @@ -0,0 +1,41 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-breadcrumb/package.json b/yanzhu-ui-app/uni_modules/uni-breadcrumb/package.json new file mode 100644 index 00000000..0a04e503 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-breadcrumb/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-breadcrumb", + "displayName": "uni-breadcrumb 面包屑", + "version": "0.1.2", + "description": "Breadcrumb 面包屑", + "keywords": [ + "uni-breadcrumb", + "breadcrumb", + "uni-ui", + "面包屑导航", + "面包屑" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-breadcrumb/readme.md b/yanzhu-ui-app/uni_modules/uni-breadcrumb/readme.md new file mode 100644 index 00000000..6976b8d7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-breadcrumb/readme.md @@ -0,0 +1,66 @@ + +## breadcrumb 面包屑导航 +> **组件名:uni-breadcrumb** +> 代码块: `ubreadcrumb` + +显示当前页面的路径,快速返回之前的任意页面。 + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +### 基本用法 + +在 ``template`` 中使用组件 + +```html + + {{route.name}} + +``` + +```js +export default { + name: "uni-stat-breadcrumb", + data() { + return { + routes: [{ + to: '/A', + name: 'A页面' + }, { + to: '/B', + name: 'B页面' + }, { + to: '/C', + name: 'C页面' + }] + }; + } + } +``` + + +## API + +### Breadcrumb Props + +|属性名 |类型 |默认值 |说明 | +|:-: |:-: |:-: |:-: | +|separator |String |斜杠'/' |分隔符 | +|separatorClass |String | |图标分隔符 class | + +### Breadcrumb Item Props + +|属性名 |类型 |默认值 |说明 | +|:-: |:-: |:-: |:-: | +|to |String | |路由跳转页面路径 | +|replace|Boolean | |在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) | + + + + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb) \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/changelog.md b/yanzhu-ui-app/uni_modules/uni-calendar/changelog.md new file mode 100644 index 00000000..f291eec0 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/changelog.md @@ -0,0 +1,26 @@ +## 1.4.10(2023-04-10) +- 修复 某些情况 monthSwitch 未触发的Bug +## 1.4.9(2023-02-02) +- 修复 某些情况切换月份错误的Bug +## 1.4.8(2023-01-30) +- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964) +## 1.4.7(2022-09-16) +- 优化 支持使用 uni-scss 控制主题色 +## 1.4.6(2022-09-08) +- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug +## 1.4.5(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式的Bug +## 1.4.4(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式的Bug +## 1.4.3(2021-09-22) +- 修复 startDate、 endDate 属性失效的Bug +## 1.4.2(2021-08-24) +- 新增 支持国际化 +## 1.4.1(2021-08-05) +- 修复 弹出层被 tabbar 遮盖的Bug +## 1.4.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.3.16(2021-05-12) +- 新增 组件示例地址 +## 1.3.15(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/calendar.js b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/calendar.js new file mode 100644 index 00000000..eb3bc067 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/calendar.js @@ -0,0 +1,546 @@ +/** +* @1900-2100区间内的公历、农历互转 +* @charset UTF-8 +* @github https://github.com/jjonline/calendar.js +* @Author Jea杨(JJonline@JJonline.Cn) +* @Time 2014-7-21 +* @Time 2016-8-13 Fixed 2033hex、Attribution Annals +* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug +* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year +* @Version 1.0.3 +* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] +* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0] +*/ +/* eslint-disable */ +var calendar = { + + /** + * 农历1900-2100的润大小信息表 + * @Array Of Property + * @return Hex + */ + lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909 + 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919 + 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929 + 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939 + 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949 + 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959 + 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969 + 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979 + 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989 + 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999 + 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009 + 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019 + 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029 + 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039 + 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049 + /** Add By JJonline@JJonline.Cn**/ + 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059 + 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069 + 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079 + 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089 + 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099 + 0x0d520], // 2100 + + /** + * 公历每个月份的天数普通表 + * @Array Of Property + * @return Number + */ + solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + + /** + * 天干地支之天干速查表 + * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] + * @return Cn string + */ + Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'], + + /** + * 天干地支之地支速查表 + * @Array Of Property + * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] + * @return Cn string + */ + Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'], + + /** + * 天干地支之地支速查表<=>生肖 + * @Array Of Property + * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] + * @return Cn string + */ + Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'], + + /** + * 24节气速查表 + * @Array Of Property + * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] + * @return Cn string + */ + solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'], + + /** + * 1900-2100各年的24节气日期速查表 + * @Array Of Property + * @return 0x string For splice + */ + sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', + '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', + 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f', + '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa', + '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f', + '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722', + '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f', + '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', + '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', + '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2', + '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', + '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', + '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721', + '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd', + '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35', + '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35', + '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'], + + /** + * 数字转中文速查表 + * @Array Of Property + * @trans ['日','一','二','三','四','五','六','七','八','九','十'] + * @return Cn string + */ + nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'], + + /** + * 日期转农历称呼速查表 + * @Array Of Property + * @trans ['初','十','廿','卅'] + * @return Cn string + */ + nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'], + + /** + * 月份转农历称呼速查表 + * @Array Of Property + * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] + * @return Cn string + */ + nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'], + + /** + * 返回农历y年一整年的总天数 + * @param lunar Year + * @return Number + * @eg:var count = calendar.lYearDays(1987) ;//count=387 + */ + lYearDays: function (y) { + var i; var sum = 348 + for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 } + return (sum + this.leapDays(y)) + }, + + /** + * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 + * @param lunar Year + * @return Number (0-12) + * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 + */ + leapMonth: function (y) { // 闰字编码 \u95f0 + return (this.lunarInfo[y - 1900] & 0xf) + }, + + /** + * 返回农历y年闰月的天数 若该年没有闰月则返回0 + * @param lunar Year + * @return Number (0、29、30) + * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 + */ + leapDays: function (y) { + if (this.leapMonth(y)) { + return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29) + } + return (0) + }, + + /** + * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 + * @param lunar Year + * @return Number (-1、29、30) + * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 + */ + monthDays: function (y, m) { + if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1 + return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29) + }, + + /** + * 返回公历(!)y年m月的天数 + * @param solar Year + * @return Number (-1、28、29、30、31) + * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 + */ + solarDays: function (y, m) { + if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1 + var ms = m - 1 + if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29 + return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28) + } else { + return (this.solarMonth[ms]) + } + }, + + /** + * 农历年份转换为干支纪年 + * @param lYear 农历年的年份数 + * @return Cn string + */ + toGanZhiYear: function (lYear) { + var ganKey = (lYear - 3) % 10 + var zhiKey = (lYear - 3) % 12 + if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干 + if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支 + return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1] + }, + + /** + * 公历月、日判断所属星座 + * @param cMonth [description] + * @param cDay [description] + * @return Cn string + */ + toAstro: function (cMonth, cDay) { + var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf' + var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] + return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座 + }, + + /** + * 传入offset偏移量返回干支 + * @param offset 相对甲子的偏移量 + * @return Cn string + */ + toGanZhi: function (offset) { + return this.Gan[offset % 10] + this.Zhi[offset % 12] + }, + + /** + * 传入公历(!)y年获得该年第n个节气的公历日期 + * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 + * @return day Number + * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 + */ + getTerm: function (y, n) { + if (y < 1900 || y > 2100) { return -1 } + if (n < 1 || n > 24) { return -1 } + var _table = this.sTermInfo[y - 1900] + var _info = [ + parseInt('0x' + _table.substr(0, 5)).toString(), + parseInt('0x' + _table.substr(5, 5)).toString(), + parseInt('0x' + _table.substr(10, 5)).toString(), + parseInt('0x' + _table.substr(15, 5)).toString(), + parseInt('0x' + _table.substr(20, 5)).toString(), + parseInt('0x' + _table.substr(25, 5)).toString() + ] + var _calday = [ + _info[0].substr(0, 1), + _info[0].substr(1, 2), + _info[0].substr(3, 1), + _info[0].substr(4, 2), + + _info[1].substr(0, 1), + _info[1].substr(1, 2), + _info[1].substr(3, 1), + _info[1].substr(4, 2), + + _info[2].substr(0, 1), + _info[2].substr(1, 2), + _info[2].substr(3, 1), + _info[2].substr(4, 2), + + _info[3].substr(0, 1), + _info[3].substr(1, 2), + _info[3].substr(3, 1), + _info[3].substr(4, 2), + + _info[4].substr(0, 1), + _info[4].substr(1, 2), + _info[4].substr(3, 1), + _info[4].substr(4, 2), + + _info[5].substr(0, 1), + _info[5].substr(1, 2), + _info[5].substr(3, 1), + _info[5].substr(4, 2) + ] + return parseInt(_calday[n - 1]) + }, + + /** + * 传入农历数字月份返回汉语通俗表示法 + * @param lunar month + * @return Cn string + * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' + */ + toChinaMonth: function (m) { // 月 => \u6708 + if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1 + var s = this.nStr3[m - 1] + s += '\u6708'// 加上月字 + return s + }, + + /** + * 传入农历日期数字返回汉字表示法 + * @param lunar day + * @return Cn string + * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' + */ + toChinaDay: function (d) { // 日 => \u65e5 + var s + switch (d) { + case 10: + s = '\u521d\u5341'; break + case 20: + s = '\u4e8c\u5341'; break + break + case 30: + s = '\u4e09\u5341'; break + break + default : + s = this.nStr2[Math.floor(d / 10)] + s += this.nStr1[d % 10] + } + return (s) + }, + + /** + * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” + * @param y year + * @return Cn string + * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' + */ + getAnimal: function (y) { + return this.Animals[(y - 4) % 12] + }, + + /** + * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON + * @param y solar year + * @param m solar month + * @param d solar day + * @return JSON object + * @eg://console.log(calendar.solar2lunar(1987,11,01)); + */ + solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31 + // 年份限定、上限 + if (y < 1900 || y > 2100) { + return -1// undefined转换为数字变为NaN + } + // 公历传参最下限 + if (y == 1900 && m == 1 && d < 31) { + return -1 + } + // 未传参 获得当天 + if (!y) { + var objDate = new Date() + } else { + var objDate = new Date(y, parseInt(m) - 1, d) + } + var i; var leap = 0; var temp = 0 + // 修正ymd参数 + var y = objDate.getFullYear() + var m = objDate.getMonth() + 1 + var d = objDate.getDate() + var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000 + for (i = 1900; i < 2101 && offset > 0; i++) { + temp = this.lYearDays(i) + offset -= temp + } + if (offset < 0) { + offset += temp; i-- + } + + // 是否今天 + var isTodayObj = new Date() + var isToday = false + if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) { + isToday = true + } + // 星期几 + var nWeek = objDate.getDay() + var cWeek = this.nStr1[nWeek] + // 数字表示周几顺应天朝周一开始的惯例 + if (nWeek == 0) { + nWeek = 7 + } + // 农历年 + var year = i + var leap = this.leapMonth(i) // 闰哪个月 + var isLeap = false + + // 效验闰月 + for (i = 1; i < 13 && offset > 0; i++) { + // 闰月 + if (leap > 0 && i == (leap + 1) && isLeap == false) { + --i + isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数 + } else { + temp = this.monthDays(year, i)// 计算农历普通月天数 + } + // 解除闰月 + if (isLeap == true && i == (leap + 1)) { isLeap = false } + offset -= temp + } + // 闰月导致数组下标重叠取反 + if (offset == 0 && leap > 0 && i == leap + 1) { + if (isLeap) { + isLeap = false + } else { + isLeap = true; --i + } + } + if (offset < 0) { + offset += temp; --i + } + // 农历月 + var month = i + // 农历日 + var day = offset + 1 + // 天干地支处理 + var sm = m - 1 + var gzY = this.toGanZhiYear(year) + + // 当月的两个节气 + // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` + var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始 + var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始 + + // 依据12节气修正干支月 + var gzM = this.toGanZhi((y - 1900) * 12 + m + 11) + if (d >= firstNode) { + gzM = this.toGanZhi((y - 1900) * 12 + m + 12) + } + + // 传入的日期的节气与否 + var isTerm = false + var Term = null + if (firstNode == d) { + isTerm = true + Term = this.solarTerm[m * 2 - 2] + } + if (secondNode == d) { + isTerm = true + Term = this.solarTerm[m * 2 - 1] + } + // 日柱 当月一日与 1900/1/1 相差天数 + var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 + var gzD = this.toGanZhi(dayCyclical + d - 1) + // 该日期所属的星座 + var astro = this.toAstro(m, d) + + return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro } + }, + + /** + * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON + * @param y lunar year + * @param m lunar month + * @param d lunar day + * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] + * @return JSON object + * @eg://console.log(calendar.lunar2solar(1987,9,10)); + */ + lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1 + var isLeapMonth = !!isLeapMonth + var leapOffset = 0 + var leapMonth = this.leapMonth(y) + var leapDay = this.leapDays(y) + if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 + if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值 + var day = this.monthDays(y, m) + var _day = day + // bugFix 2016-9-25 + // if month is leap, _day use leapDays method + if (isLeapMonth) { + _day = this.leapDays(y, m) + } + if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验 + + // 计算农历的时间差 + var offset = 0 + for (var i = 1900; i < y; i++) { + offset += this.lYearDays(i) + } + var leap = 0; var isAdd = false + for (var i = 1; i < m; i++) { + leap = this.leapMonth(y) + if (!isAdd) { // 处理闰月 + if (leap <= i && leap > 0) { + offset += this.leapDays(y); isAdd = true + } + } + offset += this.monthDays(y, i) + } + // 转换闰月农历 需补充该年闰月的前一个月的时差 + if (isLeapMonth) { offset += day } + // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) + var stmap = Date.UTC(1900, 1, 30, 0, 0, 0) + var calObj = new Date((offset + d - 31) * 86400000 + stmap) + var cY = calObj.getUTCFullYear() + var cM = calObj.getUTCMonth() + 1 + var cD = calObj.getUTCDate() + + return this.solar2lunar(cY, cM, cD) + } +} + +export default calendar diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json new file mode 100644 index 00000000..fcbd13cf --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "ok", + "uni-calender.cancel": "cancel", + "uni-calender.today": "today", + "uni-calender.MON": "MON", + "uni-calender.TUE": "TUE", + "uni-calender.WED": "WED", + "uni-calender.THU": "THU", + "uni-calender.FRI": "FRI", + "uni-calender.SAT": "SAT", + "uni-calender.SUN": "SUN" +} diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json new file mode 100644 index 00000000..1ca43de0 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "确定", + "uni-calender.cancel": "取消", + "uni-calender.today": "今日", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json new file mode 100644 index 00000000..e0fe33b9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json @@ -0,0 +1,12 @@ +{ + "uni-calender.ok": "確定", + "uni-calender.cancel": "取消", + "uni-calender.today": "今日", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六" +} diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue new file mode 100644 index 00000000..a54135ee --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue new file mode 100644 index 00000000..17c958d8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue @@ -0,0 +1,566 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/util.js b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/util.js new file mode 100644 index 00000000..5ec8a92d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/components/uni-calendar/util.js @@ -0,0 +1,360 @@ +import CALENDAR from './calendar.js' + +class Calendar { + constructor({ + date, + selected, + startDate, + endDate, + range + } = {}) { + // 当前日期 + this.date = this.getDate(new Date()) // 当前初入日期 + // 打点信息 + this.selected = selected || []; + // 范围开始 + this.startDate = startDate + // 范围结束 + this.endDate = endDate + this.range = range + // 多选状态 + this.cleanMultipleStatus() + // 每周日期 + this.weeks = {} + // this._getWeek(this.date.fullDate) + } + /** + * 设置日期 + * @param {Object} date + */ + setDate(date) { + this.selectDate = this.getDate(date) + this._getWeek(this.selectDate.fullDate) + } + + /** + * 清理多选状态 + */ + cleanMultipleStatus() { + this.multipleStatus = { + before: '', + after: '', + data: [] + } + } + + /** + * 重置开始日期 + */ + resetSatrtDate(startDate) { + // 范围开始 + this.startDate = startDate + + } + + /** + * 重置结束日期 + */ + resetEndDate(endDate) { + // 范围结束 + this.endDate = endDate + } + + /** + * 获取任意时间 + */ + getDate(date, AddDayCount = 0, str = 'day') { + if (!date) { + date = new Date() + } + if (typeof date !== 'object') { + date = date.replace(/-/g, '/') + } + const dd = new Date(date) + switch (str) { + case 'day': + dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期 + break + case 'month': + if (dd.getDate() === 31 && AddDayCount>0) { + dd.setDate(dd.getDate() + AddDayCount) + } else { + const preMonth = dd.getMonth() + dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期 + const nextMonth = dd.getMonth() + // 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题 + if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){ + dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount)) + } + // 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题 + if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){ + dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount)) + } + } + break + case 'year': + dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期 + break + } + const y = dd.getFullYear() + const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0 + const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0 + return { + fullDate: y + '-' + m + '-' + d, + year: y, + month: m, + date: d, + day: dd.getDay() + } + } + + + /** + * 获取上月剩余天数 + */ + _getLastMonthDays(firstDay, full) { + let dateArr = [] + for (let i = firstDay; i > 0; i--) { + const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() + dateArr.push({ + date: beforeDate, + month: full.month - 1, + lunar: this.getlunar(full.year, full.month - 1, beforeDate), + disable: true + }) + } + return dateArr + } + /** + * 获取本月天数 + */ + _currentMonthDys(dateData, full) { + let dateArr = [] + let fullDate = this.date.fullDate + for (let i = 1; i <= dateData; i++) { + let nowDate = full.year + '-' + (full.month < 10 ? + full.month : full.month) + '-' + (i < 10 ? + '0' + i : i) + // 是否今天 + let isDay = fullDate === nowDate + // 获取打点信息 + let info = this.selected && this.selected.find((item) => { + if (this.dateEqual(nowDate, item.date)) { + return item + } + }) + + // 日期禁用 + let disableBefore = true + let disableAfter = true + if (this.startDate) { + // let dateCompBefore = this.dateCompare(this.startDate, fullDate) + // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate) + disableBefore = this.dateCompare(this.startDate, nowDate) + } + + if (this.endDate) { + // let dateCompAfter = this.dateCompare(fullDate, this.endDate) + // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate) + disableAfter = this.dateCompare(nowDate, this.endDate) + } + let multiples = this.multipleStatus.data + let checked = false + let multiplesStatus = -1 + if (this.range) { + if (multiples) { + multiplesStatus = multiples.findIndex((item) => { + return this.dateEqual(item, nowDate) + }) + } + if (multiplesStatus !== -1) { + checked = true + } + } + let data = { + fullDate: nowDate, + year: full.year, + date: i, + multiple: this.range ? checked : false, + beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate), + afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate), + month: full.month, + lunar: this.getlunar(full.year, full.month, i), + disable: !(disableBefore && disableAfter), + isDay + } + if (info) { + data.extraInfo = info + } + + dateArr.push(data) + } + return dateArr + } + /** + * 获取下月天数 + */ + _getNextMonthDays(surplus, full) { + let dateArr = [] + for (let i = 1; i < surplus + 1; i++) { + dateArr.push({ + date: i, + month: Number(full.month) + 1, + lunar: this.getlunar(full.year, Number(full.month) + 1, i), + disable: true + }) + } + return dateArr + } + + /** + * 获取当前日期详情 + * @param {Object} date + */ + getInfo(date) { + if (!date) { + date = new Date() + } + const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) + return dateInfo + } + + /** + * 比较时间大小 + */ + dateCompare(startDate, endDate) { + // 计算截止时间 + startDate = new Date(startDate.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + endDate = new Date(endDate.replace('-', '/').replace('-', '/')) + if (startDate <= endDate) { + return true + } else { + return false + } + } + + /** + * 比较时间是否相等 + */ + dateEqual(before, after) { + // 计算截止时间 + before = new Date(before.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + after = new Date(after.replace('-', '/').replace('-', '/')) + if (before.getTime() - after.getTime() === 0) { + return true + } else { + return false + } + } + + + /** + * 获取日期范围内所有日期 + * @param {Object} begin + * @param {Object} end + */ + geDateAll(begin, end) { + var arr = [] + var ab = begin.split('-') + var ae = end.split('-') + var db = new Date() + db.setFullYear(ab[0], ab[1] - 1, ab[2]) + var de = new Date() + de.setFullYear(ae[0], ae[1] - 1, ae[2]) + var unixDb = db.getTime() - 24 * 60 * 60 * 1000 + var unixDe = de.getTime() - 24 * 60 * 60 * 1000 + for (var k = unixDb; k <= unixDe;) { + k = k + 24 * 60 * 60 * 1000 + arr.push(this.getDate(new Date(parseInt(k))).fullDate) + } + return arr + } + /** + * 计算阴历日期显示 + */ + getlunar(year, month, date) { + return CALENDAR.solar2lunar(year, month, date) + } + /** + * 设置打点 + */ + setSelectInfo(data, value) { + this.selected = value + this._getWeek(data) + } + + /** + * 获取多选状态 + */ + setMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + + if (!this.range) return + if (before && after) { + this.multipleStatus.before = '' + this.multipleStatus.after = '' + this.multipleStatus.data = [] + } else { + if (!before) { + this.multipleStatus.before = fullDate + } else { + this.multipleStatus.after = fullDate + if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); + } + } + } + this._getWeek(fullDate) + } + + /** + * 获取每周数据 + * @param {Object} dateData + */ + _getWeek(dateData) { + const { + year, + month + } = this.getDate(dateData) + let firstDay = new Date(year, month - 1, 1).getDay() + let currentDay = new Date(year, month, 0).getDate() + let dates = { + lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天 + currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数 + nextMonthDays: [], // 下个月开始几天 + weeks: [] + } + let canlender = [] + const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) + dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) + canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) + let weeks = {} + // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天 + for (let i = 0; i < canlender.length; i++) { + if (i % 7 === 0) { + weeks[parseInt(i / 7)] = new Array(7) + } + weeks[parseInt(i / 7)][i % 7] = canlender[i] + } + this.canlender = canlender + this.weeks = weeks + } + + //静态方法 + // static init(date) { + // if (!this.instance) { + // this.instance = new Calendar(date); + // } + // return this.instance; + // } +} + + +export default Calendar diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/package.json b/yanzhu-ui-app/uni_modules/uni-calendar/package.json new file mode 100644 index 00000000..fad841f3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-calendar", + "displayName": "uni-calendar 日历", + "version": "1.4.10", + "description": "日历组件", + "keywords": [ + "uni-ui", + "uniui", + "日历", + "", + "打卡", + "日历选择" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-calendar/readme.md b/yanzhu-ui-app/uni_modules/uni-calendar/readme.md new file mode 100644 index 00000000..bc159244 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-calendar/readme.md @@ -0,0 +1,103 @@ + + +## Calendar 日历 +> **组件名:uni-calendar** +> 代码块: `uCalendar` + + +日历组件 + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js) +> - 仅支持自定义组件模式 +> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date() +> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意 +> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动 + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +### 基本用法 + +在 ``template`` 中使用组件 + +```html + + + +``` + +### 通过方法打开日历 + +需要设置 `insert` 为 `false` + +```html + + + + +``` + +```javascript + +export default { + data() { + return {}; + }, + methods: { + open(){ + this.$refs.calendar.open(); + }, + confirm(e) { + //console.log(e); + } + } +}; + +``` + + +## API + +### Calendar Props + +| 属性名 | 类型 | 默认值| 说明 | +| - | - | - | - | +| date | String |- | 自定义当前时间,默认为今天 | +| lunar | Boolean | false | 显示农历 | +| startDate | String |- | 日期选择范围-开始日期 | +| endDate | String |- | 日期选择范围-结束日期 | +| range | Boolean | false | 范围选择 | +| insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 | +|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 | +| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] | +|showMonth | Boolean | true | 是否显示月份为背景 | + +### Calendar Events + +| 事件名 | 说明 |返回值| +| - | - | - | +| open | 弹出日历组件,`insert :false` 时生效|- | + + + + + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar) diff --git a/yanzhu-ui-app/uni_modules/uni-card/changelog.md b/yanzhu-ui-app/uni_modules/uni-card/changelog.md new file mode 100644 index 00000000..c3cd8c45 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-card/changelog.md @@ -0,0 +1,26 @@ +## 1.3.1(2021-12-20) +- 修复 在vue页面下略缩图显示不正常的bug +## 1.3.0(2021-11-19) +- 重构插槽的用法 ,header 替换为 title +- 新增 actions 插槽 +- 新增 cover 封面图属性和插槽 +- 新增 padding 内容默认内边距离 +- 新增 margin 卡片默认外边距离 +- 新增 spacing 卡片默认内边距 +- 新增 shadow 卡片阴影属性 +- 取消 mode 属性,可使用组合插槽代替 +- 取消 note 属性 ,使用actions插槽代替 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card) +## 1.2.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.8(2021-07-01) +- 优化 图文卡片无图片加载时,提供占位图标 +- 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持) +- 修复 thumbnail 不存在仍然占位的 bug +## 1.1.7(2021-05-12) +- 新增 组件示例地址 +## 1.1.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-card/components/uni-card/uni-card.vue b/yanzhu-ui-app/uni_modules/uni-card/components/uni-card/uni-card.vue new file mode 100644 index 00000000..88d8342f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-card/components/uni-card/uni-card.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-card/package.json b/yanzhu-ui-app/uni_modules/uni-card/package.json new file mode 100644 index 00000000..f16224de --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-card/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-card", + "displayName": "uni-card 卡片", + "version": "1.3.1", + "description": "Card 组件,提供常见的卡片样式。", + "keywords": [ + "uni-ui", + "uniui", + "card", + "", + "卡片" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-icons", + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-card/readme.md b/yanzhu-ui-app/uni_modules/uni-card/readme.md new file mode 100644 index 00000000..7434e71d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-card/readme.md @@ -0,0 +1,12 @@ + + +## Card 卡片 +> **组件名:uni-card** +> 代码块: `uCard` + +卡片视图组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-collapse/changelog.md b/yanzhu-ui-app/uni_modules/uni-collapse/changelog.md new file mode 100644 index 00000000..292e4c79 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-collapse/changelog.md @@ -0,0 +1,36 @@ +## 1.4.3(2022-01-25) +- 修复 初始化的时候 ,open 属性失效的bug +## 1.4.2(2022-01-21) +- 修复 微信小程序resize后组件收起的bug +## 1.4.1(2021-11-22) +- 修复 vue3中个别scss变量无法找到的问题 +## 1.4.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse) +## 1.3.3(2021-08-17) +- 优化 show-arrow 属性默认为true +## 1.3.2(2021-08-17) +- 新增 show-arrow 属性,控制是否显示右侧箭头 +## 1.3.1(2021-07-30) +- 优化 vue3下小程序事件警告的问题 +## 1.3.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.2.2(2021-07-21) +- 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug +## 1.2.1(2021-07-21) +- 优化 组件示例 +## 1.2.0(2021-07-21) +- 新增 组件折叠动画 +- 新增 value\v-model 属性 ,动态修改面板折叠状态 +- 新增 title 插槽 ,可定义面板标题 +- 新增 border 属性 ,显示隐藏面板内容分隔线 +- 新增 title-border 属性 ,显示隐藏面板标题分隔线 +- 修复 resize 方法失效的Bug +- 修复 change 事件返回参数不正确的Bug +- 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法 +## 1.1.7(2021-05-12) +- 新增 组件示例地址 +## 1.1.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.1.5(2021-02-05) +- 调整为uni_modules目录规范 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue b/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue new file mode 100644 index 00000000..4181c185 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue b/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue new file mode 100644 index 00000000..f461c148 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue @@ -0,0 +1,147 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-collapse/package.json b/yanzhu-ui-app/uni_modules/uni-collapse/package.json new file mode 100644 index 00000000..65349cf9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-collapse/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-collapse", + "displayName": "uni-collapse 折叠面板", + "version": "1.4.3", + "description": "Collapse 组件,可以折叠 / 展开的内容区域。", + "keywords": [ + "uni-ui", + "折叠", + "折叠面板", + "手风琴" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-collapse/readme.md b/yanzhu-ui-app/uni_modules/uni-collapse/readme.md new file mode 100644 index 00000000..bc758ebc --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-collapse/readme.md @@ -0,0 +1,12 @@ + + +## Collapse 折叠面板 +> **组件名:uni-collapse** +> 代码块: `uCollapse` +> 关联组件:`uni-collapse-item`、`uni-icons`。 + + +折叠面板用来折叠/显示过长的内容或者是列表。通常是在多内容分类项使用,折叠不重要的内容,显示重要内容。点击可以展开折叠部分。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-collapse) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-combox/changelog.md b/yanzhu-ui-app/uni_modules/uni-combox/changelog.md new file mode 100644 index 00000000..23c27485 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-combox/changelog.md @@ -0,0 +1,15 @@ +## 1.0.1(2021-11-23) +- 优化 label、label-width 属性 +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-combox](https://uniapp.dcloud.io/component/uniui/uni-combox) +## 0.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.6(2021-05-12) +- 新增 组件示例地址 +## 0.0.5(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 0.0.4(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 0.0.3(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue b/yanzhu-ui-app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue new file mode 100644 index 00000000..83454e58 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue @@ -0,0 +1,294 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-combox/package.json b/yanzhu-ui-app/uni_modules/uni-combox/package.json new file mode 100644 index 00000000..4a05c3ff --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-combox/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-combox", + "displayName": "uni-combox 组合框", + "version": "1.0.1", + "description": "可以选择也可以输入的表单项 ", + "keywords": [ + "uni-ui", + "uniui", + "combox", + "组合框", + "select" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-combox/readme.md b/yanzhu-ui-app/uni_modules/uni-combox/readme.md new file mode 100644 index 00000000..ffa2cc86 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-combox/readme.md @@ -0,0 +1,11 @@ + + +## Combox 组合框 +> **组件名:uni-combox** +> 代码块: `uCombox` + + +组合框组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-combox) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/changelog.md b/yanzhu-ui-app/uni_modules/uni-countdown/changelog.md new file mode 100644 index 00000000..f25beefc --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/changelog.md @@ -0,0 +1,24 @@ +## 1.2.2(2022-01-19) +- 修复 在微信小程序中样式不生效的bug +## 1.2.1(2022-01-18) +- 新增 update 方法 ,在动态更新时间后,刷新组件 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown) +## 1.1.3(2021-10-18) +- 重构 +- 新增 font-size 支持自定义字体大小 +## 1.1.2(2021-08-24) +- 新增 支持国际化 +## 1.1.1(2021-07-30) +- 优化 vue3下小程序事件警告的问题 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.5(2021-06-18) +- 修复 uni-countdown 重复赋值跳两秒的 bug +## 1.0.4(2021-05-12) +- 新增 组件示例地址 +## 1.0.3(2021-05-08) +- 修复 uni-countdown 不能控制倒计时的 bug +## 1.0.2(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json new file mode 100644 index 00000000..06309cb0 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "day", + "uni-countdown.h": "h", + "uni-countdown.m": "m", + "uni-countdown.s": "s" +} diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json new file mode 100644 index 00000000..358cdd16 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "天", + "uni-countdown.h": "时", + "uni-countdown.m": "分", + "uni-countdown.s": "秒" +} diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json new file mode 100644 index 00000000..e5a63dea --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json @@ -0,0 +1,6 @@ +{ + "uni-countdown.day": "天", + "uni-countdown.h": "時", + "uni-countdown.m": "分", + "uni-countdown.s": "秒" +} diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue new file mode 100644 index 00000000..65a1216c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue @@ -0,0 +1,267 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/package.json b/yanzhu-ui-app/uni_modules/uni-countdown/package.json new file mode 100644 index 00000000..70e99ee7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-countdown", + "displayName": "uni-countdown 倒计时", + "version": "1.2.2", + "description": "CountDown 倒计时组件", + "keywords": [ + "uni-ui", + "uniui", + "countdown", + "倒计时" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-countdown/readme.md b/yanzhu-ui-app/uni_modules/uni-countdown/readme.md new file mode 100644 index 00000000..4bcb1aa7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-countdown/readme.md @@ -0,0 +1,10 @@ + + +## CountDown 倒计时 +> **组件名:uni-countdown** +> 代码块: `uCountDown` + +倒计时组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-data-checkbox/changelog.md b/yanzhu-ui-app/uni_modules/uni-data-checkbox/changelog.md new file mode 100644 index 00000000..c7a468a2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-checkbox/changelog.md @@ -0,0 +1,45 @@ +## 1.0.3(2022-09-16) +- 可以使用 uni-scss 控制主题色 +## 1.0.2(2022-06-30) +- 优化 在 uni-forms 中的依赖注入方式 +## 1.0.1(2022-02-07) +- 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) +## 0.2.5(2021-08-23) +- 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题 +## 0.2.4(2021-08-17) +- 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 +## 0.2.3(2021-08-11) +- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 +## 0.2.2(2021-07-30) +- 优化 在uni-forms组件,与label不对齐的问题 +## 0.2.1(2021-07-27) +- 修复 单选默认值为0不能选中的Bug +## 0.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.1.11(2021-07-06) +- 优化 删除无用日志 +## 0.1.10(2021-07-05) +- 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题 +## 0.1.9(2021-07-05) +- 修复 nvue 黑框样式问题 +## 0.1.8(2021-06-28) +- 修复 selectedTextColor 属性不生效的Bug +## 0.1.7(2021-06-02) +- 新增 map 属性,可以方便映射text/value属性 +## 0.1.6(2021-05-26) +- 修复 不关联服务空间的情况下组件报错的Bug +## 0.1.5(2021-05-12) +- 新增 组件示例地址 +## 0.1.4(2021-04-09) +- 修复 nvue 下无法选中的问题 +## 0.1.3(2021-03-22) +- 新增 disabled属性 +## 0.1.2(2021-02-24) +- 优化 默认颜色显示 +## 0.1.1(2021-02-24) +- 新增 支持nvue +## 0.1.0(2021-02-18) +- “暂无数据”显示居中 diff --git a/yanzhu-ui-app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue b/yanzhu-ui-app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue new file mode 100644 index 00000000..3c75d9f4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue @@ -0,0 +1,821 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-data-checkbox/package.json b/yanzhu-ui-app/uni_modules/uni-data-checkbox/package.json new file mode 100644 index 00000000..113c3505 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-checkbox/package.json @@ -0,0 +1,84 @@ +{ + "id": "uni-data-checkbox", + "displayName": "uni-data-checkbox 数据选择器", + "version": "1.0.3", + "description": "通过数据驱动的单选框和复选框", + "keywords": [ + "uni-ui", + "checkbox", + "单选", + "多选", + "单选多选" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.1" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-load-more","uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-data-checkbox/readme.md b/yanzhu-ui-app/uni_modules/uni-data-checkbox/readme.md new file mode 100644 index 00000000..6eb253d4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-checkbox/readme.md @@ -0,0 +1,18 @@ + + +## DataCheckbox 数据驱动的单选复选框 +> **组件名:uni-data-checkbox** +> 代码块: `uDataCheckbox` + + +本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括: + +1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能 +2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验 +3. 本组件合并了单选多选 +4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性 + +在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/changelog.md b/yanzhu-ui-app/uni_modules/uni-data-picker/changelog.md new file mode 100644 index 00000000..1dd79f76 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/changelog.md @@ -0,0 +1,75 @@ +## 1.1.2(2023-04-11) +- 修复 更改 modelValue 报错的 bug +- 修复 v-for 未使用 key 值控制台 warning +## 1.1.1(2023-02-21) +- 修复代码合并时引发 value 属性为空时不渲染数据的问题 +## 1.1.0(2023-02-15) +- 修复 localdata 不支持动态更新的bug +## 1.0.9(2023-02-15) +- 修复 localdata 不支持动态更新的bug +## 1.0.8(2022-09-16) +- 可以使用 uni-scss 控制主题色 +## 1.0.7(2022-07-06) +- 优化 pc端图标位置不正确的问题 +## 1.0.6(2022-07-05) +- 优化 显示样式 +## 1.0.5(2022-07-04) +- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug +## 1.0.4(2022-04-19) +- 修复 字节小程序 本地数据无法选择下一级的Bug +## 1.0.3(2022-02-25) +- 修复 nvue 不支持的 v-show 的 bug +## 1.0.2(2022-02-25) +- 修复 条件编译 nvue 不支持的 css 样式 +## 1.0.1(2021-11-23) +- 修复 由上个版本引发的map、v-model等属性不生效的bug +## 1.0.0(2021-11-19) +- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker) +## 0.4.9(2021-10-28) +- 修复 VUE2 v-model 概率无效的 bug +## 0.4.8(2021-10-27) +- 修复 v-model 概率无效的 bug +## 0.4.7(2021-10-25) +- 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+ +- 修复 树型 uniCloud 数据类型为 int 时报错的 bug +## 0.4.6(2021-10-19) +- 修复 非 VUE3 v-model 为 0 时无法选中的 bug +## 0.4.5(2021-09-26) +- 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效 +- 修复 readonly 为 true 时报错的 bug +## 0.4.4(2021-09-26) +- 修复 上一版本造成的 map 属性失效的 bug +- 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略 +## 0.4.3(2021-09-24) +- 修复 某些情况下级联未触发的 bug +## 0.4.2(2021-09-23) +- 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用 +- 新增 选项内容过长自动添加省略号 +## 0.4.1(2021-09-15) +- 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段 +## 0.4.0(2021-07-13) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.3.5(2021-06-04) +- 修复 无法加载云端数据的问题 +## 0.3.4(2021-05-28) +- 修复 v-model 无效问题 +- 修复 loaddata 为空数据组时加载时间过长问题 +- 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点 +## 0.3.3(2021-05-12) +- 新增 组件示例地址 +## 0.3.2(2021-04-22) +- 修复 非树形数据有 where 属性查询报错的问题 +## 0.3.1(2021-04-15) +- 修复 本地数据概率无法回显时问题 +## 0.3.0(2021-04-07) +- 新增 支持云端非树形表结构数据 +- 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题 +## 0.2.0(2021-03-15) +- 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题 +## 0.1.9(2021-03-09) +- 修复 微信小程序某些情况下无法选择的问题 +## 0.1.8(2021-02-05) +- 优化 部分样式在 nvue 上的兼容表现 +## 0.1.7(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js new file mode 100644 index 00000000..6ef26a26 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue new file mode 100644 index 00000000..179a4e0b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue @@ -0,0 +1,551 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js new file mode 100644 index 00000000..cfae22a4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js @@ -0,0 +1,622 @@ +export default { + props: { + localdata: { + type: [Array, Object], + default () { + return [] + } + }, + spaceInfo: { + type: Object, + default () { + return {} + } + }, + collection: { + type: String, + default: '' + }, + action: { + type: String, + default: '' + }, + field: { + type: String, + default: '' + }, + orderby: { + type: String, + default: '' + }, + where: { + type: [String, Object], + default: '' + }, + pageData: { + type: String, + default: 'add' + }, + pageCurrent: { + type: Number, + default: 1 + }, + pageSize: { + type: Number, + default: 500 + }, + getcount: { + type: [Boolean, String], + default: false + }, + getone: { + type: [Boolean, String], + default: false + }, + gettree: { + type: [Boolean, String], + default: false + }, + manual: { + type: Boolean, + default: false + }, + value: { + type: [Array, String, Number], + default () { + return [] + } + }, + modelValue: { + type: [Array, String, Number], + default () { + return [] + } + }, + preload: { + type: Boolean, + default: false + }, + stepSearh: { + type: Boolean, + default: true + }, + selfField: { + type: String, + default: '' + }, + parentField: { + type: String, + default: '' + }, + multiple: { + type: Boolean, + default: false + }, + map: { + type: Object, + default () { + return { + text: "text", + value: "value" + } + } + } + }, + data() { + return { + loading: false, + errorMessage: '', + loadMore: { + contentdown: '', + contentrefresh: '', + contentnomore: '' + }, + dataList: [], + selected: [], + selectedIndex: 0, + page: { + current: this.pageCurrent, + size: this.pageSize, + count: 0 + } + } + }, + computed: { + isLocalData() { + return !this.collection.length; + }, + isCloudData() { + return this.collection.length > 0; + }, + isCloudDataList() { + return (this.isCloudData && (!this.parentField && !this.selfField)); + }, + isCloudDataTree() { + return (this.isCloudData && this.parentField && this.selfField); + }, + dataValue() { + let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || + this.modelValue !== undefined); + return isModelValue ? this.modelValue : this.value; + }, + hasValue() { + if (typeof this.dataValue === 'number') { + return true + } + return (this.dataValue != null) && (this.dataValue.length > 0) + } + }, + created() { + this.$watch(() => { + var al = []; + ['pageCurrent', + 'pageSize', + 'spaceInfo', + 'value', + 'modelValue', + 'localdata', + 'collection', + 'action', + 'field', + 'orderby', + 'where', + 'getont', + 'getcount', + 'gettree' + ].forEach(key => { + al.push(this[key]) + }); + return al + }, (newValue, oldValue) => { + let needReset = false + for (let i = 2; i < newValue.length; i++) { + if (newValue[i] != oldValue[i]) { + needReset = true + break + } + } + if (newValue[0] != oldValue[0]) { + this.page.current = this.pageCurrent + } + this.page.size = this.pageSize + + this.onPropsChange() + }) + this._treeData = [] + }, + methods: { + onPropsChange() { + this._treeData = []; + }, + + // 填充 pickview 数据 + async loadData() { + if (this.isLocalData) { + this.loadLocalData(); + } else if (this.isCloudDataList) { + this.loadCloudDataList(); + } else if (this.isCloudDataTree) { + this.loadCloudDataTree(); + } + }, + + // 加载本地数据 + async loadLocalData() { + this._treeData = []; + this._extractTree(this.localdata, this._treeData); + + let inputValue = this.dataValue; + if (inputValue === undefined) { + return; + } + + if (Array.isArray(inputValue)) { + inputValue = inputValue[inputValue.length - 1]; + if (typeof inputValue === 'object' && inputValue[this.map.value]) { + inputValue = inputValue[this.map.value]; + } + } + + this.selected = this._findNodePath(inputValue, this.localdata); + }, + + // 加载 Cloud 数据 (单列) + async loadCloudDataList() { + if (this.loading) { + return; + } + this.loading = true; + + try { + let response = await this.getCommand(); + let responseData = response.result.data; + + this._treeData = responseData; + + this._updateBindData(); + this._updateSelected(); + + this.onDataChange(); + } catch (e) { + this.errorMessage = e; + } finally { + this.loading = false; + } + }, + + // 加载 Cloud 数据 (树形) + async loadCloudDataTree() { + if (this.loading) { + return; + } + this.loading = true; + + try { + let commandOptions = { + field: this._cloudDataPostField(), + where: this._cloudDataTreeWhere() + }; + if (this.gettree) { + commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`; + } + + let response = await this.getCommand(commandOptions); + let responseData = response.result.data; + + this._treeData = responseData; + this._updateBindData(); + this._updateSelected(); + + this.onDataChange(); + } catch (e) { + this.errorMessage = e; + } finally { + this.loading = false; + } + }, + + // 加载 Cloud 数据 (节点) + async loadCloudDataNode(callback) { + if (this.loading) { + return; + } + this.loading = true; + + try { + let commandOptions = { + field: this._cloudDataPostField(), + where: this._cloudDataNodeWhere() + }; + + let response = await this.getCommand(commandOptions); + let responseData = response.result.data; + + callback(responseData); + } catch (e) { + this.errorMessage = e; + } finally { + this.loading = false; + } + }, + + // 回显 Cloud 数据 + getCloudDataValue() { + if (this.isCloudDataList) { + return this.getCloudDataListValue(); + } + + if (this.isCloudDataTree) { + return this.getCloudDataTreeValue(); + } + }, + + // 回显 Cloud 数据 (单列) + getCloudDataListValue() { + // 根据 field's as value标识匹配 where 条件 + let where = []; + let whereField = this._getForeignKeyByField(); + if (whereField) { + where.push(`${whereField} == '${this.dataValue}'`) + } + + where = where.join(' || '); + + if (this.where) { + where = `(${this.where}) && (${where})` + } + + return this.getCommand({ + field: this._cloudDataPostField(), + where + }).then((res) => { + this.selected = res.result.data; + return res.result.data; + }); + }, + + // 回显 Cloud 数据 (树形) + getCloudDataTreeValue() { + return this.getCommand({ + field: this._cloudDataPostField(), + getTreePath: { + startWith: `${this.selfField}=='${this.dataValue}'` + } + }).then((res) => { + let treePath = []; + this._extractTreePath(res.result.data, treePath); + this.selected = treePath; + return treePath; + }); + }, + + getCommand(options = {}) { + /* eslint-disable no-undef */ + let db = uniCloud.database(this.spaceInfo) + + const action = options.action || this.action + if (action) { + db = db.action(action) + } + + const collection = options.collection || this.collection + db = db.collection(collection) + + const where = options.where || this.where + if (!(!where || !Object.keys(where).length)) { + db = db.where(where) + } + + const field = options.field || this.field + if (field) { + db = db.field(field) + } + + const orderby = options.orderby || this.orderby + if (orderby) { + db = db.orderBy(orderby) + } + + const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current + const size = options.pageSize !== undefined ? options.pageSize : this.page.size + const getCount = options.getcount !== undefined ? options.getcount : this.getcount + const getTree = options.gettree !== undefined ? options.gettree : this.gettree + + const getOptions = { + getCount, + getTree + } + if (options.getTreePath) { + getOptions.getTreePath = options.getTreePath + } + + db = db.skip(size * (current - 1)).limit(size).get(getOptions) + + return db + }, + + _cloudDataPostField() { + let fields = [this.field]; + if (this.parentField) { + fields.push(`${this.parentField} as parent_value`); + } + return fields.join(','); + }, + + _cloudDataTreeWhere() { + let result = [] + let selected = this.selected + let parentField = this.parentField + if (parentField) { + result.push(`${parentField} == null || ${parentField} == ""`) + } + if (selected.length) { + for (var i = 0; i < selected.length - 1; i++) { + result.push(`${parentField} == '${selected[i].value}'`) + } + } + + let where = [] + if (this.where) { + where.push(`(${this.where})`) + } + + if (result.length) { + where.push(`(${result.join(' || ')})`) + } + + return where.join(' && ') + }, + + _cloudDataNodeWhere() { + let where = [] + let selected = this.selected; + if (selected.length) { + where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`); + } + + where = where.join(' || '); + + if (this.where) { + return `(${this.where}) && (${where})` + } + + return where + }, + + _getWhereByForeignKey() { + let result = [] + let whereField = this._getForeignKeyByField(); + if (whereField) { + result.push(`${whereField} == '${this.dataValue}'`) + } + + if (this.where) { + return `(${this.where}) && (${result.join(' || ')})` + } + + return result.join(' || ') + }, + + _getForeignKeyByField() { + let fields = this.field.split(','); + let whereField = null; + for (let i = 0; i < fields.length; i++) { + const items = fields[i].split('as'); + if (items.length < 2) { + continue; + } + if (items[1].trim() === 'value') { + whereField = items[0].trim(); + break; + } + } + return whereField; + }, + + _updateBindData(node) { + const { + dataList, + hasNodes + } = this._filterData(this._treeData, this.selected) + + let isleaf = this._stepSearh === false && !hasNodes + + if (node) { + node.isleaf = isleaf + } + + this.dataList = dataList + this.selectedIndex = dataList.length - 1 + + if (!isleaf && this.selected.length < dataList.length) { + this.selected.push({ + value: null, + text: "请选择" + }) + } + + return { + isleaf, + hasNodes + } + }, + + _updateSelected() { + let dl = this.dataList + let sl = this.selected + let textField = this.map.text + let valueField = this.map.value + for (let i = 0; i < sl.length; i++) { + let value = sl[i].value + let dl2 = dl[i] + for (let j = 0; j < dl2.length; j++) { + let item2 = dl2[j] + if (item2[valueField] === value) { + sl[i].text = item2[textField] + break + } + } + } + }, + + _filterData(data, paths) { + let dataList = [] + let hasNodes = true + + dataList.push(data.filter((item) => { + return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '') + })) + for (let i = 0; i < paths.length; i++) { + let value = paths[i].value + let nodes = data.filter((item) => { + return item.parent_value === value + }) + + if (nodes.length) { + dataList.push(nodes) + } else { + hasNodes = false + } + } + + return { + dataList, + hasNodes + } + }, + + _extractTree(nodes, result, parent_value) { + let list = result || [] + let valueField = this.map.value + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + + let child = {} + for (let key in node) { + if (key !== 'children') { + child[key] = node[key] + } + } + if (parent_value !== null && parent_value !== undefined && parent_value !== '') { + child.parent_value = parent_value + } + result.push(child) + + let children = node.children + if (children) { + this._extractTree(children, result, node[valueField]) + } + } + }, + + _extractTreePath(nodes, result) { + let list = result || [] + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + + let child = {} + for (let key in node) { + if (key !== 'children') { + child[key] = node[key] + } + } + result.push(child) + + let children = node.children + if (children) { + this._extractTreePath(children, result) + } + } + }, + + _findNodePath(key, nodes, path = []) { + let textField = this.map.text + let valueField = this.map.value + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] + let children = node.children + let text = node[textField] + let value = node[valueField] + + path.push({ + value, + text + }) + + if (value === key) { + return path + } + + if (children) { + const p = this._findNodePath(key, children, path) + if (p.length) { + return p + } + } + + path.pop() + } + return [] + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue new file mode 100644 index 00000000..6ebced92 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue @@ -0,0 +1,323 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/package.json b/yanzhu-ui-app/uni_modules/uni-data-picker/package.json new file mode 100644 index 00000000..038f9ce9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/package.json @@ -0,0 +1,90 @@ +{ + "id": "uni-data-picker", + "displayName": "uni-data-picker 数据驱动的picker选择器", + "version": "1.1.2", + "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景", + "keywords": [ + "uni-ui", + "uniui", + "picker", + "级联", + "省市区", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-load-more", + "uni-icons", + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-data-picker/readme.md b/yanzhu-ui-app/uni_modules/uni-data-picker/readme.md new file mode 100644 index 00000000..6cda2240 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-picker/readme.md @@ -0,0 +1,22 @@ +## DataPicker 级联选择 +> **组件名:uni-data-picker** +> 代码块: `uDataPicker` +> 关联组件:`uni-data-pickerview`、`uni-load-more`。 + + +`` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。 + +支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 + +候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。 + +`` 组件尤其适用于地址选择、分类选择等选择类。 + +`` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。 + +`` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。 + +在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-data-select/changelog.md b/yanzhu-ui-app/uni_modules/uni-data-select/changelog.md new file mode 100644 index 00000000..eb3d1cea --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-select/changelog.md @@ -0,0 +1,35 @@ +## 1.0.6(2023-04-12) +- 修复 微信小程序点击时会改变背景颜色的 bug +## 1.0.5(2023-02-03) +- 修复 禁用时会显示清空按钮 +## 1.0.4(2023-02-02) +- 优化 查询条件短期内多次变更只查询最后一次变更后的结果 +- 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue +## 1.0.3(2023-01-16) +- 修复 不关联服务空间报错的问题 +## 1.0.2(2023-01-14) +- 新增 属性 `format` 可用于格式化显示选项内容 +## 1.0.1(2022-12-06) +- 修复 当where变化时,数据不会自动更新的问题 +## 0.1.9(2022-09-05) +- 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框 +## 0.1.8(2022-08-29) +- 修复 点击的位置不准确 +## 0.1.7(2022-08-12) +- 新增 支持 disabled 属性 +## 0.1.6(2022-07-06) +- 修复 pc端宽度异常的bug +## 0.1.5 +- 修复 pc端宽度异常的bug +## 0.1.4(2022-07-05) +- 优化 显示样式 +## 0.1.3(2022-06-02) +- 修复 localdata 赋值不生效的 bug +- 新增 支持 uni.scss 修改颜色 +- 新增 支持选项禁用(数据选项设置 disabled: true 即禁用) +## 0.1.2(2022-05-08) +- 修复 当 value 为 0 时选择不生效的 bug +## 0.1.1(2022-05-07) +- 新增 记住上次的选项(仅 collection 存在时有效) +## 0.1.0(2022-04-22) +- 初始化 diff --git a/yanzhu-ui-app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue b/yanzhu-ui-app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue new file mode 100644 index 00000000..9b323485 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue @@ -0,0 +1,517 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-data-select/package.json b/yanzhu-ui-app/uni_modules/uni-data-select/package.json new file mode 100644 index 00000000..01874292 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-select/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-data-select", + "displayName": "uni-data-select 下拉框选择器", + "version": "1.0.6", + "description": "通过数据驱动的下拉框选择器", + "keywords": [ + "uni-ui", + "select", + "uni-data-select", + "下拉框", + "下拉选" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.1" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-load-more"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "u", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-data-select/readme.md b/yanzhu-ui-app/uni_modules/uni-data-select/readme.md new file mode 100644 index 00000000..eb58de30 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-data-select/readme.md @@ -0,0 +1,8 @@ +## DataSelect 下拉框选择器 +> **组件名:uni-data-select** +> 代码块: `uDataSelect` + +当选项过多时,使用下拉菜单展示并选择内容 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/yanzhu-ui-app/uni_modules/uni-dateformat/changelog.md b/yanzhu-ui-app/uni_modules/uni-dateformat/changelog.md new file mode 100644 index 00000000..d551d7b8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-dateformat/changelog.md @@ -0,0 +1,10 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat) +## 0.0.5(2021-07-08) +- 调整 默认时间不再是当前时间,而是显示'-'字符 +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-02-04) +- 调整为uni_modules目录规范 +- 修复 iOS 平台日期格式化出错的问题 diff --git a/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js new file mode 100644 index 00000000..e00d5597 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js @@ -0,0 +1,200 @@ +// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型 +function pad(str, length = 2) { + str += '' + while (str.length < length) { + str = '0' + str + } + return str.slice(-length) +} + +const parser = { + yyyy: (dateObj) => { + return pad(dateObj.year, 4) + }, + yy: (dateObj) => { + return pad(dateObj.year) + }, + MM: (dateObj) => { + return pad(dateObj.month) + }, + M: (dateObj) => { + return dateObj.month + }, + dd: (dateObj) => { + return pad(dateObj.day) + }, + d: (dateObj) => { + return dateObj.day + }, + hh: (dateObj) => { + return pad(dateObj.hour) + }, + h: (dateObj) => { + return dateObj.hour + }, + mm: (dateObj) => { + return pad(dateObj.minute) + }, + m: (dateObj) => { + return dateObj.minute + }, + ss: (dateObj) => { + return pad(dateObj.second) + }, + s: (dateObj) => { + return dateObj.second + }, + SSS: (dateObj) => { + return pad(dateObj.millisecond, 3) + }, + S: (dateObj) => { + return dateObj.millisecond + }, +} + +// 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12 +function getDate(time) { + if (time instanceof Date) { + return time + } + switch (typeof time) { + case 'string': + { + // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000 + if (time.indexOf('T') > -1) { + return new Date(time) + } + return new Date(time.replace(/-/g, '/')) + } + default: + return new Date(time) + } +} + +export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') { + if (!date && date !== 0) { + return '' + } + date = getDate(date) + const dateObj = { + year: date.getFullYear(), + month: date.getMonth() + 1, + day: date.getDate(), + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + millisecond: date.getMilliseconds() + } + const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/ + let flag = true + let result = format + while (flag) { + flag = false + result = result.replace(tokenRegExp, function(matched) { + flag = true + return parser[matched](dateObj) + }) + } + return result +} + +export function friendlyDate(time, { + locale = 'zh', + threshold = [60000, 3600000], + format = 'yyyy/MM/dd hh:mm:ss' +}) { + if (time === '-') { + return time + } + if (!time && time !== 0) { + return '' + } + const localeText = { + zh: { + year: '年', + month: '月', + day: '天', + hour: '小时', + minute: '分钟', + second: '秒', + ago: '前', + later: '后', + justNow: '刚刚', + soon: '马上', + template: '{num}{unit}{suffix}' + }, + en: { + year: 'year', + month: 'month', + day: 'day', + hour: 'hour', + minute: 'minute', + second: 'second', + ago: 'ago', + later: 'later', + justNow: 'just now', + soon: 'soon', + template: '{num} {unit} {suffix}' + } + } + const text = localeText[locale] || localeText.zh + let date = getDate(time) + let ms = date.getTime() - Date.now() + let absMs = Math.abs(ms) + if (absMs < threshold[0]) { + return ms < 0 ? text.justNow : text.soon + } + if (absMs >= threshold[1]) { + return formatDate(date, format) + } + let num + let unit + let suffix = text.later + if (ms < 0) { + suffix = text.ago + ms = -ms + } + const seconds = Math.floor((ms) / 1000) + const minutes = Math.floor(seconds / 60) + const hours = Math.floor(minutes / 60) + const days = Math.floor(hours / 24) + const months = Math.floor(days / 30) + const years = Math.floor(months / 12) + switch (true) { + case years > 0: + num = years + unit = text.year + break + case months > 0: + num = months + unit = text.month + break + case days > 0: + num = days + unit = text.day + break + case hours > 0: + num = hours + unit = text.hour + break + case minutes > 0: + num = minutes + unit = text.minute + break + default: + num = seconds + unit = text.second + break + } + + if (locale === 'en') { + if (num === 1) { + num = 'a' + } else { + unit += 's' + } + } + + return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g, + suffix) +} diff --git a/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue new file mode 100644 index 00000000..c5ed0307 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-dateformat/package.json b/yanzhu-ui-app/uni_modules/uni-dateformat/package.json new file mode 100644 index 00000000..786a670b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-dateformat/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-dateformat", + "displayName": "uni-dateformat 日期格式化", + "version": "1.0.0", + "description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式", + "keywords": [ + "uni-ui", + "uniui", + "日期格式化", + "时间格式化", + "格式化时间", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-dateformat/readme.md b/yanzhu-ui-app/uni_modules/uni-dateformat/readme.md new file mode 100644 index 00000000..37ddb6ec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-dateformat/readme.md @@ -0,0 +1,11 @@ + + +### DateFormat 日期格式化 +> **组件名:uni-dateformat** +> 代码块: `uDateformat` + + +日期格式化组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-dateformat) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/changelog.md b/yanzhu-ui-app/uni_modules/uni-datetime-picker/changelog.md new file mode 100644 index 00000000..1f1a5549 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/changelog.md @@ -0,0 +1,133 @@ +## 2.2.22(2023-03-30) +- 修复 日历 picker 修改年月后,自动选中当月1日 [详情](https://ask.dcloud.net.cn/question/165937) +- 修复 小程序端 低版本 ios NaN [详情](https://ask.dcloud.net.cn/question/162979) +## 2.2.21(2023-02-20) +- 修复 firefox 浏览器显示区域点击无法拉起日历弹框的Bug [详情](https://ask.dcloud.net.cn/question/163362) +## 2.2.20(2023-02-17) +- 优化 值为空依然选中当天问题 +- 优化 提供 default-value 属性支持配置选择器打开时默认显示的时间 +- 优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间 +- 优化 字节小程序日期时间范围选择,底部日期换行问题 +## 2.2.19(2023-02-09) +- 修复 2.2.18 引起范围选择配置 end 选择无效的Bug [详情](https://github.com/dcloudio/uni-ui/issues/686) +## 2.2.18(2023-02-08) +- 修复 移动端范围选择change事件触发异常的Bug [详情](https://github.com/dcloudio/uni-ui/issues/684) +- 优化 PC端输入日期格式错误时返回当前日期时间 +- 优化 PC端输入日期时间超出 start、end 限制的Bug +- 优化 移动端日期时间范围用法时间展示不完整问题 +## 2.2.17(2023-02-04) +- 修复 小程序端绑定 Date 类型报错的Bug [详情](https://github.com/dcloudio/uni-ui/issues/679) +- 修复 vue3 time-picker 无法显示绑定时分秒的Bug +## 2.2.16(2023-02-02) +- 修复 字节小程序报错的Bug +## 2.2.15(2023-02-02) +- 修复 某些情况切换月份错误的Bug +## 2.2.14(2023-01-30) +- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/162033) +## 2.2.13(2023-01-10) +- 修复 多次加载组件造成内存占用的Bug +## 2.2.12(2022-12-01) +- 修复 vue3 下 i18n 国际化初始值不正确的Bug +## 2.2.11(2022-09-19) +- 修复 支付宝小程序样式错乱的Bug [详情](https://github.com/dcloudio/uni-app/issues/3861) +## 2.2.10(2022-09-19) +- 修复 反向选择日期范围,日期显示异常的Bug [详情](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false) +## 2.2.9(2022-09-16) +- 可以使用 uni-scss 控制主题色 +## 2.2.8(2022-09-08) +- 修复 close事件无效的Bug +## 2.2.7(2022-09-05) +- 修复 移动端 maskClick 无效的Bug [详情](https://ask.dcloud.net.cn/question/140824) +## 2.2.6(2022-06-30) +- 优化 组件样式,调整了组件图标大小、高度、颜色等,与uni-ui风格保持一致 +## 2.2.5(2022-06-24) +- 修复 日历顶部年月及底部确认未国际化的Bug +## 2.2.4(2022-03-31) +- 修复 Vue3 下动态赋值,单选类型未响应的Bug +## 2.2.3(2022-03-28) +- 修复 Vue3 下动态赋值未响应的Bug +## 2.2.2(2021-12-10) +- 修复 clear-icon 属性在小程序平台不生效的Bug +## 2.2.1(2021-12-10) +- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的Bug +## 2.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源 [详情](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移 [https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) +## 2.1.5(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 2.1.4(2021-09-10) +- 修复 hide-second 在移动端的Bug +- 修复 单选赋默认值时,赋值日期未高亮的Bug +- 修复 赋默认值时,移动端未正确显示时间的Bug +## 2.1.3(2021-09-09) +- 新增 hide-second 属性,支持只使用时分,隐藏秒 +## 2.1.2(2021-09-03) +- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次 +- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法 +- 优化 调整字号大小,美化日历界面 +- 修复 因国际化导致的 placeholder 失效的Bug +## 2.1.1(2021-08-24) +- 新增 支持国际化 +- 优化 范围选择器在 pc 端过宽的问题 +## 2.1.0(2021-08-09) +- 新增 适配 vue3 +## 2.0.19(2021-08-09) +- 新增 支持作为 uni-forms 子组件相关功能 +- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的Bug +## 2.0.18(2021-08-05) +- 修复 type 属性动态赋值无效的Bug +- 修复 ‘确认’按钮被 tabbar 遮盖 bug +- 修复 组件未赋值时范围选左、右日历相同的Bug +## 2.0.17(2021-08-04) +- 修复 范围选未正确显示当前值的Bug +- 修复 h5 平台(移动端)报错 'cale' of undefined 的Bug +## 2.0.16(2021-07-21) +- 新增 return-type 属性支持返回 date 日期对象 +## 2.0.15(2021-07-14) +- 修复 单选日期类型,初始赋值后不在当前日历的Bug +- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效) +- 优化 移动端移除显示框的清空按钮,无实际用途 +## 2.0.14(2021-07-14) +- 修复 组件赋值为空,界面未更新的Bug +- 修复 start 和 end 不能动态赋值的Bug +- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的Bug +## 2.0.13(2021-07-08) +- 修复 范围选择不能动态赋值的Bug +## 2.0.12(2021-07-08) +- 修复 范围选择的初始时间在一个月内时,造成无法选择的bug +## 2.0.11(2021-07-08) +- 优化 弹出层在超出视窗边缘定位不准确的问题 +## 2.0.10(2021-07-08) +- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的Bug +- 优化 弹出层在超出视窗边缘被遮盖的问题 +## 2.0.9(2021-07-07) +- 新增 maskClick 事件 +- 修复 特殊情况日历 rpx 布局错误的Bug,rpx -> px +- 修复 范围选择时清空返回值不合理的bug,['', ''] -> [] +## 2.0.8(2021-07-07) +- 新增 日期时间显示框支持插槽 +## 2.0.7(2021-07-01) +- 优化 添加 uni-icons 依赖 +## 2.0.6(2021-05-22) +- 修复 图标在小程序上不显示的Bug +- 优化 重命名引用组件,避免潜在组件命名冲突 +## 2.0.5(2021-05-20) +- 优化 代码目录扁平化 +## 2.0.4(2021-05-12) +- 新增 组件示例地址 +## 2.0.3(2021-05-10) +- 修复 ios 下不识别 '-' 日期格式的Bug +- 优化 pc 下弹出层添加边框和阴影 +## 2.0.2(2021-05-08) +- 修复 在 admin 中获取弹出层定位错误的bug +## 2.0.1(2021-05-08) +- 修复 type 属性向下兼容,默认值从 date 变更为 datetime +## 2.0.0(2021-04-30) +- 支持日历形式的日期+时间的范围选择 + > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker) +## 1.0.6(2021-03-18) +- 新增 hide-second 属性,时间支持仅选择时、分 +- 修复 选择跟显示的日期不一样的Bug +- 修复 chang事件触发2次的Bug +- 修复 分、秒 end 范围错误的Bug +- 优化 更好的 nvue 适配 diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue new file mode 100644 index 00000000..dba98879 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue new file mode 100644 index 00000000..3418f49c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue @@ -0,0 +1,928 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json new file mode 100644 index 00000000..024f22f6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json @@ -0,0 +1,22 @@ +{ + "uni-datetime-picker.selectDate": "select date", + "uni-datetime-picker.selectTime": "select time", + "uni-datetime-picker.selectDateTime": "select date and time", + "uni-datetime-picker.startDate": "start date", + "uni-datetime-picker.endDate": "end date", + "uni-datetime-picker.startTime": "start time", + "uni-datetime-picker.endTime": "end time", + "uni-datetime-picker.ok": "ok", + "uni-datetime-picker.clear": "clear", + "uni-datetime-picker.cancel": "cancel", + "uni-datetime-picker.year": "-", + "uni-datetime-picker.month": "", + "uni-calender.MON": "MON", + "uni-calender.TUE": "TUE", + "uni-calender.WED": "WED", + "uni-calender.THU": "THU", + "uni-calender.FRI": "FRI", + "uni-calender.SAT": "SAT", + "uni-calender.SUN": "SUN", + "uni-calender.confirm": "confirm" +} diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json new file mode 100644 index 00000000..d2df5e72 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json @@ -0,0 +1,22 @@ +{ + "uni-datetime-picker.selectDate": "选择日期", + "uni-datetime-picker.selectTime": "选择时间", + "uni-datetime-picker.selectDateTime": "选择日期时间", + "uni-datetime-picker.startDate": "开始日期", + "uni-datetime-picker.endDate": "结束日期", + "uni-datetime-picker.startTime": "开始时间", + "uni-datetime-picker.endTime": "结束时间", + "uni-datetime-picker.ok": "确定", + "uni-datetime-picker.clear": "清除", + "uni-datetime-picker.cancel": "取消", + "uni-datetime-picker.year": "年", + "uni-datetime-picker.month": "月", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六", + "uni-calender.confirm": "确认" +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json new file mode 100644 index 00000000..d23fa3c3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json @@ -0,0 +1,22 @@ +{ + "uni-datetime-picker.selectDate": "選擇日期", + "uni-datetime-picker.selectTime": "選擇時間", + "uni-datetime-picker.selectDateTime": "選擇日期時間", + "uni-datetime-picker.startDate": "開始日期", + "uni-datetime-picker.endDate": "結束日期", + "uni-datetime-picker.startTime": "開始时间", + "uni-datetime-picker.endTime": "結束时间", + "uni-datetime-picker.ok": "確定", + "uni-datetime-picker.clear": "清除", + "uni-datetime-picker.cancel": "取消", + "uni-datetime-picker.year": "年", + "uni-datetime-picker.month": "月", + "uni-calender.SUN": "日", + "uni-calender.MON": "一", + "uni-calender.TUE": "二", + "uni-calender.WED": "三", + "uni-calender.THU": "四", + "uni-calender.FRI": "五", + "uni-calender.SAT": "六", + "uni-calender.confirm": "確認" +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue new file mode 100644 index 00000000..81a042a2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue @@ -0,0 +1,934 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue new file mode 100644 index 00000000..bd964880 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue @@ -0,0 +1,1026 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js new file mode 100644 index 00000000..7dc34c4c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js @@ -0,0 +1,403 @@ +class Calendar { + constructor({ + selected, + startDate, + endDate, + range, + } = {}) { + // 当前日期 + this.date = this.getDateObj(new Date()) // 当前初入日期 + // 打点信息 + this.selected = selected || []; + // 起始时间 + this.startDate = startDate + // 终止时间 + this.endDate = endDate + // 是否范围选择 + this.range = range + // 多选状态 + this.cleanMultipleStatus() + // 每周日期 + this.weeks = {} + this.lastHover = false + } + /** + * 设置日期 + * @param {Object} date + */ + setDate(date) { + const selectDate = this.getDateObj(date) + this.getWeeks(selectDate.fullDate) + } + + /** + * 清理多选状态 + */ + cleanMultipleStatus() { + this.multipleStatus = { + before: '', + after: '', + data: [] + } + } + + setStartDate(startDate) { + this.startDate = startDate + } + + setEndDate(endDate) { + this.endDate = endDate + } + + getPreMonthObj(date){ + date = fixIosDateFormat(date) + date = new Date(date) + + const oldMonth = date.getMonth() + date.setMonth(oldMonth - 1) + const newMonth = date.getMonth() + if(oldMonth !== 0 && newMonth - oldMonth === 0){ + date.setMonth(newMonth - 1) + } + return this.getDateObj(date) + } + getNextMonthObj(date){ + date = fixIosDateFormat(date) + date = new Date(date) + + const oldMonth = date.getMonth() + date.setMonth(oldMonth + 1) + const newMonth = date.getMonth() + if(newMonth - oldMonth > 1){ + date.setMonth(newMonth - 1) + } + return this.getDateObj(date) + } + + /** + * 获取指定格式Date对象 + */ + getDateObj(date) { + date = fixIosDateFormat(date) + date = new Date(date) + + return { + fullDate: getDate(date), + year: date.getFullYear(), + month: addZero(date.getMonth() + 1), + date: addZero(date.getDate()), + day: date.getDay() + } + } + + /** + * 获取上一个月日期集合 + */ + getPreMonthDays(amount, dateObj) { + const result = [] + for (let i = amount - 1; i >= 0; i--) { + const month = dateObj.month - 1 + result.push({ + date: new Date(dateObj.year, month, -i).getDate(), + month, + disable: true + }) + } + return result + } + /** + * 获取本月日期集合 + */ + getCurrentMonthDays(amount, dateObj) { + const result = [] + const fullDate = this.date.fullDate + for (let i = 1; i <= amount; i++) { + const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}` + const isToday = fullDate === currentDate + // 获取打点信息 + const info = this.selected && this.selected.find((item) => { + if (this.dateEqual(currentDate, item.date)) { + return item + } + }) + + // 日期禁用 + let disableBefore = true + let disableAfter = true + if (this.startDate) { + disableBefore = dateCompare(this.startDate, currentDate) + } + + if (this.endDate) { + disableAfter = dateCompare(currentDate, this.endDate) + } + + let multiples = this.multipleStatus.data + let multiplesStatus = -1 + if (this.range && multiples) { + multiplesStatus = multiples.findIndex((item) => { + return this.dateEqual(item, currentDate) + }) + } + const checked = multiplesStatus !== -1 + + result.push({ + fullDate: currentDate, + year: dateObj.year, + date: i, + multiple: this.range ? checked : false, + beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after), + afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after), + month: dateObj.month, + disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)), + isToday, + userChecked: false, + extraInfo: info + }) + } + return result + } + /** + * 获取下一个月日期集合 + */ + _getNextMonthDays(amount, dateObj) { + const result = [] + const month = dateObj.month + 1 + for (let i = 1; i <= amount; i++) { + result.push({ + date: i, + month, + disable: true + }) + } + return result + } + + /** + * 获取当前日期详情 + * @param {Object} date + */ + getInfo(date) { + if (!date) { + date = new Date() + } + + return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate) + } + + /** + * 比较时间是否相等 + */ + dateEqual(before, after) { + before = new Date(fixIosDateFormat(before)) + after = new Date(fixIosDateFormat(after)) + return before.valueOf() === after.valueOf() + } + + /** + * 比较真实起始日期 + */ + + isLogicBefore(currentDate, before, after) { + let logicBefore = before + if (before && after) { + logicBefore = dateCompare(before, after) ? before : after + } + return this.dateEqual(logicBefore, currentDate) + } + + isLogicAfter(currentDate, before, after) { + let logicAfter = after + if (before && after) { + logicAfter = dateCompare(before, after) ? after : before + } + return this.dateEqual(logicAfter, currentDate) + } + + /** + * 获取日期范围内所有日期 + * @param {Object} begin + * @param {Object} end + */ + geDateAll(begin, end) { + var arr = [] + var ab = begin.split('-') + var ae = end.split('-') + var db = new Date() + db.setFullYear(ab[0], ab[1] - 1, ab[2]) + var de = new Date() + de.setFullYear(ae[0], ae[1] - 1, ae[2]) + var unixDb = db.getTime() - 24 * 60 * 60 * 1000 + var unixDe = de.getTime() - 24 * 60 * 60 * 1000 + for (var k = unixDb; k <= unixDe;) { + k = k + 24 * 60 * 60 * 1000 + arr.push(this.getDateObj(new Date(parseInt(k))).fullDate) + } + return arr + } + + /** + * 获取多选状态 + */ + setMultiple(fullDate) { + if (!this.range) return + + let { + before, + after + } = this.multipleStatus + if (before && after) { + if (!this.lastHover) { + this.lastHover = true + return + } + this.multipleStatus.before = fullDate + this.multipleStatus.after = '' + this.multipleStatus.data = [] + this.multipleStatus.fulldate = '' + this.lastHover = false + } else { + if (!before) { + this.multipleStatus.before = fullDate + this.lastHover = false + } else { + this.multipleStatus.after = fullDate + if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus + .after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus + .before); + } + this.lastHover = true + } + } + this.getWeeks(fullDate) + } + + /** + * 鼠标 hover 更新多选状态 + */ + setHoverMultiple(fullDate) { + if (!this.range || this.lastHover) return + + const { before } = this.multipleStatus + + if (!before) { + this.multipleStatus.before = fullDate + } else { + this.multipleStatus.after = fullDate + if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); + } + } + this.getWeeks(fullDate) + } + + /** + * 更新默认值多选状态 + */ + setDefaultMultiple(before, after) { + this.multipleStatus.before = before + this.multipleStatus.after = after + if (before && after) { + if (dateCompare(before, after)) { + this.multipleStatus.data = this.geDateAll(before, after); + this.getWeeks(after) + } else { + this.multipleStatus.data = this.geDateAll(after, before); + this.getWeeks(before) + } + } + } + + /** + * 获取每周数据 + * @param {Object} dateData + */ + getWeeks(dateData) { + const { + year, + month, + } = this.getDateObj(dateData) + + const preMonthDayAmount = new Date(year, month - 1, 1).getDay() + const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData)) + + const currentMonthDayAmount = new Date(year, month, 0).getDate() + const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData)) + + const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount + const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData)) + + const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays] + + const weeks = new Array(6) + for (let i = 0; i < calendarDays.length; i++) { + const index = Math.floor(i / 7) + if(!weeks[index]){ + weeks[index] = new Array(7) + } + weeks[index][i % 7] = calendarDays[i] + } + + this.calendar = calendarDays + this.weeks = weeks + } +} + +function getDateTime(date, hideSecond){ + return `${getDate(date)} ${getTime(date, hideSecond)}` +} + +function getDate(date) { + date = fixIosDateFormat(date) + date = new Date(date) + const year = date.getFullYear() + const month = date.getMonth()+1 + const day = date.getDate() + return `${year}-${addZero(month)}-${addZero(day)}` +} + +function getTime(date, hideSecond){ + date = fixIosDateFormat(date) + date = new Date(date) + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}` +} + +function addZero(num) { + if(num < 10){ + num = `0${num}` + } + return num +} + +function getDefaultSecond(hideSecond) { + return hideSecond ? '00:00' : '00:00:00' +} + +function dateCompare(startDate, endDate) { + startDate = new Date(fixIosDateFormat(startDate)) + endDate = new Date(fixIosDateFormat(endDate)) + return startDate <= endDate +} + +function checkDate(date){ + const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g + return date.match(dateReg) +} + +const dateTimeReg = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])( [0-5][0-9]:[0-5][0-9]:[0-5][0-9])?$/ +function fixIosDateFormat(value) { + if (typeof value === 'string' && dateTimeReg.test(value)) { + value = value.replace(/-/g, '/') + } + return value +} + +export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/package.json b/yanzhu-ui-app/uni_modules/uni-datetime-picker/package.json new file mode 100644 index 00000000..8abed63f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-datetime-picker", + "displayName": "uni-datetime-picker 日期选择器", + "version": "2.2.22", + "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择", + "keywords": [ + "uni-datetime-picker", + "uni-ui", + "uniui", + "日期时间选择器", + "日期时间" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-datetime-picker/readme.md b/yanzhu-ui-app/uni_modules/uni-datetime-picker/readme.md new file mode 100644 index 00000000..162fbefa --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-datetime-picker/readme.md @@ -0,0 +1,21 @@ + + +> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护` + +## DatetimePicker 时间选择器 + +> **组件名:uni-datetime-picker** +> 代码块: `uDatetimePicker` + + +该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。 + +若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。 + +**_点击 picker 默认值规则:_** + +- 若设置初始值 value, 会显示在 picker 显示框中 +- 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-drawer/changelog.md b/yanzhu-ui-app/uni_modules/uni-drawer/changelog.md new file mode 100644 index 00000000..6d2488c3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-drawer/changelog.md @@ -0,0 +1,13 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中个别scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer) +## 1.1.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/keypress.js b/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/keypress.js new file mode 100644 index 00000000..62dda461 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue b/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue new file mode 100644 index 00000000..82331a81 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-drawer/package.json b/yanzhu-ui-app/uni_modules/uni-drawer/package.json new file mode 100644 index 00000000..dd056e4c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-drawer/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-drawer", + "displayName": "uni-drawer 抽屉", + "version": "1.2.1", + "description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。", + "keywords": [ + "uni-ui", + "uniui", + "drawer", + "抽屉", + "侧滑导航" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-drawer/readme.md b/yanzhu-ui-app/uni_modules/uni-drawer/readme.md new file mode 100644 index 00000000..dcf6e6b2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-drawer/readme.md @@ -0,0 +1,10 @@ + + +## Drawer 抽屉 +> **组件名:uni-drawer** +> 代码块: `uDrawer` + +抽屉侧滑菜单。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-drawer) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-easyinput/changelog.md b/yanzhu-ui-app/uni_modules/uni-easyinput/changelog.md new file mode 100644 index 00000000..765401ac --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-easyinput/changelog.md @@ -0,0 +1,97 @@ +## 1.1.9(2023-04-11) +- 修复 vue3 下 keyboardheightchange 事件报错的bug +## 1.1.8(2023-03-29) +- 优化 trim 属性默认值 +## 1.1.7(2023-03-29) +- 新增 cursor-spacing 属性 +## 1.1.6(2023-01-28) +- 新增 keyboardheightchange 事件,可监听键盘高度变化 +## 1.1.5(2022-11-29) +- 优化 主题样式 +## 1.1.4(2022-10-27) +- 修复 props 中背景颜色无默认值的bug +## 1.1.0(2022-06-30) + +- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容 +- 新增 clear 事件,点击右侧叉号图标触发 +- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发 +- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等 + +## 1.0.5(2022-06-07) + +- 优化 clearable 显示策略 + +## 1.0.4(2022-06-07) + +- 优化 clearable 显示策略 + +## 1.0.3(2022-05-20) + +- 修复 关闭图标某些情况下无法取消的 bug + +## 1.0.2(2022-04-12) + +- 修复 默认值不生效的 bug + +## 1.0.1(2022-04-02) + +- 修复 value 不能为 0 的 bug + +## 1.0.0(2021-11-19) + +- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput) + +## 0.1.4(2021-08-20) + +- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug + +## 0.1.3(2021-08-11) + +- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 + +## 0.1.2(2021-07-30) + +- 优化 vue3 下事件警告的问题 + +## 0.1.1 + +- 优化 errorMessage 属性支持 Boolean 类型 + +## 0.1.0(2021-07-13) + +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) + +## 0.0.16(2021-06-29) + +- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug + +## 0.0.15(2021-06-21) + +- 修复 passwordIcon 属性拼写错误的 bug + +## 0.0.14(2021-06-18) + +- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标 +- 修复 confirmType 属性不生效的问题 + +## 0.0.13(2021-06-04) + +- 修复 disabled 状态可清出内容的 bug + +## 0.0.12(2021-05-12) + +- 新增 组件示例地址 + +## 0.0.11(2021-05-07) + +- 修复 input-border 属性不生效的问题 + +## 0.0.10(2021-04-30) + +- 修复 ios 遮挡文字、显示一半的问题 + +## 0.0.9(2021-02-05) + +- 调整为 uni_modules 目录规范 +- 优化 兼容 nvue 页面 diff --git a/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/common.js new file mode 100644 index 00000000..f6854e1f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/common.js @@ -0,0 +1,56 @@ +/** + * @desc 函数防抖 + * @param func 目标函数 + * @param wait 延迟执行毫秒数 + * @param immediate true - 立即执行, false - 延迟执行 + */ +export const debounce = function(func, wait = 1000, immediate = true) { + let timer; + //console.log(1); + return function() { + //console.log(123); + let context = this, + args = arguments; + if (timer) clearTimeout(timer); + if (immediate) { + let callNow = !timer; + timer = setTimeout(() => { + timer = null; + }, wait); + if (callNow) func.apply(context, args); + } else { + timer = setTimeout(() => { + func.apply(context, args); + }, wait) + } + } +} +/** + * @desc 函数节流 + * @param func 函数 + * @param wait 延迟执行毫秒数 + * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发 + */ +export const throttle = (func, wait = 1000, type = 1) => { + let previous = 0; + let timeout; + return function() { + let context = this; + let args = arguments; + if (type === 1) { + let now = Date.now(); + + if (now - previous > wait) { + func.apply(context, args); + previous = now; + } + } else if (type === 2) { + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + func.apply(context, args) + }, wait) + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue new file mode 100644 index 00000000..224c1698 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue @@ -0,0 +1,657 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-easyinput/package.json b/yanzhu-ui-app/uni_modules/uni-easyinput/package.json new file mode 100644 index 00000000..bd128e17 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-easyinput/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-easyinput", + "displayName": "uni-easyinput 增强输入框", + "version": "1.1.9", + "description": "Easyinput 组件是对原生input组件的增强", + "keywords": [ + "uni-ui", + "uniui", + "input", + "uni-easyinput", + "输入框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-easyinput/readme.md b/yanzhu-ui-app/uni_modules/uni-easyinput/readme.md new file mode 100644 index 00000000..f1faf8fb --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-easyinput/readme.md @@ -0,0 +1,11 @@ + + +### Easyinput 增强输入框 +> **组件名:uni-easyinput** +> 代码块: `uEasyinput` + + +easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-fab/changelog.md b/yanzhu-ui-app/uni_modules/uni-fab/changelog.md new file mode 100644 index 00000000..9bd47292 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fab/changelog.md @@ -0,0 +1,23 @@ +## 1.2.5(2023-03-29) +- 新增 pattern.icon 属性,可自定义图标 +## 1.2.4(2022-09-07) +小程序端由于 style 使用了对象导致报错,[详情](https://ask.dcloud.net.cn/question/152790?item_id=211778&rf=false) +## 1.2.3(2022-09-05) +- 修复 nvue 环境下,具有 tabBar 时,fab 组件下部位置无法正常获取 --window-bottom 的bug,详见:[https://ask.dcloud.net.cn/question/110638?notification_id=826310](https://ask.dcloud.net.cn/question/110638?notification_id=826310) +## 1.2.2(2021-12-29) +- 更新 组件依赖 +## 1.2.1(2021-11-19) +- 修复 阴影颜色不正确的bug +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fab](https://uniapp.dcloud.io/component/uniui/uni-fab) +## 1.1.1(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 按钮背景色调整 +- 优化 兼容pc端 diff --git a/yanzhu-ui-app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/yanzhu-ui-app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue new file mode 100644 index 00000000..dfa65c1b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue @@ -0,0 +1,491 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-fab/package.json b/yanzhu-ui-app/uni_modules/uni-fab/package.json new file mode 100644 index 00000000..18c08102 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fab/package.json @@ -0,0 +1,84 @@ +{ + "id": "uni-fab", + "displayName": "uni-fab 悬浮按钮", + "version": "1.2.5", + "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。", + "keywords": [ + "uni-ui", + "uniui", + "按钮", + "悬浮按钮", + "fab" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-fab/readme.md b/yanzhu-ui-app/uni_modules/uni-fab/readme.md new file mode 100644 index 00000000..9a444e88 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fab/readme.md @@ -0,0 +1,9 @@ +## Fab 悬浮按钮 +> **组件名:uni-fab** +> 代码块: `uFab` + + +点击可展开一个图形按钮菜单 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fab) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-fav/changelog.md b/yanzhu-ui-app/uni_modules/uni-fav/changelog.md new file mode 100644 index 00000000..d8a08d43 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/changelog.md @@ -0,0 +1,19 @@ +## 1.2.1(2022-05-30) +- 新增 stat 属性 ,是否开启uni统计功能 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fav](https://uniapp.dcloud.io/component/uniui/uni-fav) +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.6(2021-05-12) +- 新增 组件示例地址 +## 1.0.5(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.4(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.3(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.2(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/en.json new file mode 100644 index 00000000..9a0759e0 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/en.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "collect", + "uni-fav.collected": "collected" +} diff --git a/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json new file mode 100644 index 00000000..67c89bfc --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "收藏", + "uni-fav.collected": "已收藏" +} diff --git a/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json new file mode 100644 index 00000000..67c89bfc --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json @@ -0,0 +1,4 @@ +{ + "uni-fav.collect": "收藏", + "uni-fav.collected": "已收藏" +} diff --git a/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue new file mode 100644 index 00000000..d2c58df9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue @@ -0,0 +1,161 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-fav/package.json b/yanzhu-ui-app/uni_modules/uni-fav/package.json new file mode 100644 index 00000000..cc146971 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-fav", + "displayName": "uni-fav 收藏按钮", + "version": "1.2.1", + "description": " Fav 收藏组件,可自定义颜色、大小。", + "keywords": [ + "fav", + "uni-ui", + "uniui", + "收藏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-fav/readme.md b/yanzhu-ui-app/uni_modules/uni-fav/readme.md new file mode 100644 index 00000000..4de125d2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-fav/readme.md @@ -0,0 +1,10 @@ + + +## Fav 收藏按钮 +> **组件名:uni-fav** +> 代码块: `uFav` + +用于收藏功能,可点击切换选中、不选中的状态。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fav) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/changelog.md b/yanzhu-ui-app/uni_modules/uni-file-picker/changelog.md new file mode 100644 index 00000000..b8230e9f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/changelog.md @@ -0,0 +1,67 @@ +## 1.0.4(2023-03-29) +- 修复 手动上传删除一个文件后不能再上传的bug +## 1.0.3(2022-12-19) +- 新增 sourceType 属性, 可以自定义图片和视频选择的来源 +## 1.0.2(2022-07-04) +- 修复 在uni-forms下样式不生效的bug +## 1.0.1(2021-11-23) +- 修复 参数为对象的情况下,url在某些情况显示错误的bug +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker) +## 0.2.16(2021-11-08) +- 修复 传入空对象 ,显示错误的Bug +## 0.2.15(2021-08-30) +- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug +## 0.2.14(2021-08-23) +- 新增 参数中返回 fileID 字段 +## 0.2.13(2021-08-23) +- 修复 腾讯云传入fileID 不能回显的bug +- 修复 选择图片后,不能放大的问题 +## 0.2.12(2021-08-17) +- 修复 由于 0.2.11 版本引起的不能回显图片的Bug +## 0.2.11(2021-08-16) +- 新增 clearFiles(index) 方法,可以手动删除指定文件 +- 修复 v-model 值设为 null 报错的Bug +## 0.2.10(2021-08-13) +- 修复 return-type="object" 时,无法删除文件的Bug +## 0.2.9(2021-08-03) +- 修复 auto-upload 属性失效的Bug +## 0.2.8(2021-07-31) +- 修复 fileExtname属性不指定值报错的Bug +## 0.2.7(2021-07-31) +- 修复 在某种场景下图片不回显的Bug +## 0.2.6(2021-07-30) +- 修复 return-type为object下,返回值不正确的Bug +## 0.2.5(2021-07-30) +- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题 +## 0.2.3(2021-07-28) +- 优化 调整示例代码 +## 0.2.2(2021-07-27) +- 修复 vue3 下赋值错误的Bug +- 优化 h5平台下上传文件导致页面卡死的问题 +## 0.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.1.1(2021-07-02) +- 修复 sourceType 缺少默认值导致 ios 无法选择文件 +## 0.1.0(2021-06-30) +- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改 +## 0.0.11(2021-06-30) +- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题 +## 0.0.10(2021-06-29) +- 优化 文件上传后进度条消失时机 +## 0.0.9(2021-06-29) +- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug +## 0.0.8(2021-06-15) +- 修复 删除文件时无法触发 v-model 的Bug +## 0.0.7(2021-05-12) +- 新增 组件示例地址 +## 0.0.6(2021-04-09) +- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug +## 0.0.5(2021-04-09) +- 优化 更新组件示例 +## 0.0.4(2021-04-09) +- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js new file mode 100644 index 00000000..aff0864c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js @@ -0,0 +1,224 @@ +'use strict'; + +const ERR_MSG_OK = 'chooseAndUploadFile:ok'; +const ERR_MSG_FAIL = 'chooseAndUploadFile:fail'; + +function chooseImage(opts) { + const { + count, + sizeType = ['original', 'compressed'], + sourceType, + extension + } = opts + return new Promise((resolve, reject) => { + uni.chooseImage({ + count, + sizeType, + sourceType, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res, 'image')); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseVideo(opts) { + const { + camera, + compressed, + maxDuration, + sourceType, + extension + } = opts; + return new Promise((resolve, reject) => { + uni.chooseVideo({ + camera, + compressed, + maxDuration, + sourceType, + extension, + success(res) { + const { + tempFilePath, + duration, + size, + height, + width + } = res; + resolve(normalizeChooseAndUploadFileRes({ + errMsg: 'chooseVideo:ok', + tempFilePaths: [tempFilePath], + tempFiles: [ + { + name: (res.tempFile && res.tempFile.name) || '', + path: tempFilePath, + size, + type: (res.tempFile && res.tempFile.type) || '', + width, + height, + duration, + fileType: 'video', + cloudPath: '', + }, ], + }, 'video')); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseAll(opts) { + const { + count, + extension + } = opts; + return new Promise((resolve, reject) => { + let chooseFile = uni.chooseFile; + if (typeof wx !== 'undefined' && + typeof wx.chooseMessageFile === 'function') { + chooseFile = wx.chooseMessageFile; + } + if (typeof chooseFile !== 'function') { + return reject({ + errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。', + }); + } + chooseFile({ + type: 'all', + count, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res)); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function normalizeChooseAndUploadFileRes(res, fileType) { + res.tempFiles.forEach((item, index) => { + if (!item.name) { + item.name = item.path.substring(item.path.lastIndexOf('/') + 1); + } + if (fileType) { + item.fileType = fileType; + } + item.cloudPath = + Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.')); + }); + if (!res.tempFilePaths) { + res.tempFilePaths = res.tempFiles.map((file) => file.path); + } + return res; +} + +function uploadCloudFiles(files, max = 5, onUploadProgress) { + files = JSON.parse(JSON.stringify(files)) + const len = files.length + let count = 0 + let self = this + return new Promise(resolve => { + while (count < max) { + next() + } + + function next() { + let cur = count++ + if (cur >= len) { + !files.find(item => !item.url && !item.errMsg) && resolve(files) + return + } + const fileItem = files[cur] + const index = self.files.findIndex(v => v.uuid === fileItem.uuid) + fileItem.url = '' + delete fileItem.errMsg + + uniCloud + .uploadFile({ + filePath: fileItem.path, + cloudPath: fileItem.cloudPath, + fileType: fileItem.fileType, + onUploadProgress: res => { + res.index = index + onUploadProgress && onUploadProgress(res) + } + }) + .then(res => { + fileItem.url = res.fileID + fileItem.index = index + if (cur < len) { + next() + } + }) + .catch(res => { + fileItem.errMsg = res.errMsg || res.message + fileItem.index = index + if (cur < len) { + next() + } + }) + } + }) +} + + + + + +function uploadFiles(choosePromise, { + onChooseFile, + onUploadProgress +}) { + return choosePromise + .then((res) => { + if (onChooseFile) { + const customChooseRes = onChooseFile(res); + if (typeof customChooseRes !== 'undefined') { + return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ? + res : chooseRes); + } + } + return res; + }) + .then((res) => { + if (res === false) { + return { + errMsg: ERR_MSG_OK, + tempFilePaths: [], + tempFiles: [], + }; + } + return res + }) +} + +function chooseAndUploadFile(opts = { + type: 'all' +}) { + if (opts.type === 'image') { + return uploadFiles(chooseImage(opts), opts); + } + else if (opts.type === 'video') { + return uploadFiles(chooseVideo(opts), opts); + } + return uploadFiles(chooseAll(opts), opts); +} + +export { + chooseAndUploadFile, + uploadCloudFiles +}; diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue new file mode 100644 index 00000000..a9a72e2d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue @@ -0,0 +1,667 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue new file mode 100644 index 00000000..625d92ec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue @@ -0,0 +1,325 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue new file mode 100644 index 00000000..2a29bc23 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js new file mode 100644 index 00000000..60aaa3e4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js @@ -0,0 +1,109 @@ +/** + * 获取文件名和后缀 + * @param {String} name + */ +export const get_file_ext = (name) => { + const last_len = name.lastIndexOf('.') + const len = name.length + return { + name: name.substring(0, last_len), + ext: name.substring(last_len + 1, len) + } +} + +/** + * 获取扩展名 + * @param {Array} fileExtname + */ +export const get_extname = (fileExtname) => { + if (!Array.isArray(fileExtname)) { + let extname = fileExtname.replace(/(\[|\])/g, '') + return extname.split(',') + } else { + return fileExtname + } + return [] +} + +/** + * 获取文件和检测是否可选 + */ +export const get_files_and_is_max = (res, _extname) => { + let filePaths = [] + let files = [] + if(!_extname || _extname.length === 0){ + return { + filePaths, + files + } + } + res.tempFiles.forEach(v => { + let fileFullName = get_file_ext(v.name) + const extname = fileFullName.ext.toLowerCase() + if (_extname.indexOf(extname) !== -1) { + files.push(v) + filePaths.push(v.path) + } + }) + if (files.length !== res.tempFiles.length) { + uni.showToast({ + title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`, + icon: 'none', + duration: 5000 + }) + } + + return { + filePaths, + files + } +} + + +/** + * 获取图片信息 + * @param {Object} filepath + */ +export const get_file_info = (filepath) => { + return new Promise((resolve, reject) => { + uni.getImageInfo({ + src: filepath, + success(res) { + resolve(res) + }, + fail(err) { + reject(err) + } + }) + }) +} +/** + * 获取封装数据 + */ +export const get_file_data = async (files, type = 'image') => { + // 最终需要上传数据库的数据 + let fileFullName = get_file_ext(files.name) + const extname = fileFullName.ext.toLowerCase() + let filedata = { + name: files.name, + uuid: files.uuid, + extname: extname || '', + cloudPath: files.cloudPath, + fileType: files.fileType, + url: files.path || files.path, + size: files.size, //单位是字节 + image: {}, + path: files.path, + video: {} + } + if (type === 'image') { + const imageinfo = await get_file_info(files.path) + delete filedata.video + filedata.image.width = imageinfo.width + filedata.image.height = imageinfo.height + filedata.image.location = imageinfo.path + } else { + delete filedata.image + } + return filedata +} diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/package.json b/yanzhu-ui-app/uni_modules/uni-file-picker/package.json new file mode 100644 index 00000000..35c926c9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-file-picker", + "displayName": "uni-file-picker 文件选择上传", + "version": "1.0.4", + "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间", + "keywords": [ + "uni-ui", + "uniui", + "图片上传", + "文件上传" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-file-picker/readme.md b/yanzhu-ui-app/uni_modules/uni-file-picker/readme.md new file mode 100644 index 00000000..c8399a5e --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-file-picker/readme.md @@ -0,0 +1,11 @@ + +## FilePicker 文件选择上传 + +> **组件名:uni-file-picker** +> 代码块: `uFilePicker` + + +文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-forms/changelog.md b/yanzhu-ui-app/uni_modules/uni-forms/changelog.md new file mode 100644 index 00000000..8218df5f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/changelog.md @@ -0,0 +1,92 @@ +## 1.4.9(2023-02-10) +- 修复 required 参数无法动态绑定 +## 1.4.8(2022-08-23) +- 优化 根据 rules 自动添加 required 的问题 +## 1.4.7(2022-08-22) +- 修复 item 未设置 require 属性,rules 设置 require 后,星号也显示的 bug,详见:[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540) +## 1.4.6(2022-07-13) +- 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug +## 1.4.5(2022-07-05) +- 新增 更多表单示例 +- 优化 子表单组件过期提示的问题 +- 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式 +## 1.4.4(2022-07-04) +- 更新 删除组件日志 +## 1.4.3(2022-07-04) +- 修复 由 1.4.0 引发的 label 插槽不生效的bug +## 1.4.2(2022-07-04) +- 修复 子组件找不到 setValue 报错的bug +## 1.4.1(2022-07-04) +- 修复 uni-data-picker 在 uni-forms-item 中报错的bug +- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug +## 1.4.0(2022-06-30) +- 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题 +- 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力 +- 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃 +- 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效 +- 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法 +- 新增 子表单的 setRules 方法,配合自定义校验函数使用 +- 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则 +- 优化 动态表单校验方式,废弃拼接name的方式 +## 1.3.3(2022-06-22) +- 修复 表单校验顺序无序问题 +## 1.3.2(2021-12-09) +- +## 1.3.1(2021-11-19) +- 修复 label 插槽不生效的bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms) +## 1.2.7(2021-08-13) +- 修复 没有添加校验规则的字段依然报错的Bug +## 1.2.6(2021-08-11) +- 修复 重置表单错误信息无法清除的问题 +## 1.2.5(2021-08-11) +- 优化 组件文档 +## 1.2.4(2021-08-11) +- 修复 表单验证只生效一次的问题 +## 1.2.3(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.2(2021-07-26) +- 修复 vue2 下条件编译导致destroyed生命周期失效的Bug +- 修复 1.2.1 引起的示例在小程序平台报错的Bug +## 1.2.1(2021-07-22) +- 修复 动态校验表单,默认值为空的情况下校验失效的Bug +- 修复 不指定name属性时,运行报错的Bug +- 优化 label默认宽度从65调整至70,使required为true且四字时不换行 +- 优化 组件示例,新增动态校验示例代码 +- 优化 组件文档,使用方式更清晰 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.2(2021-06-25) +- 修复 pattern 属性在微信小程序平台无效的问题 +## 1.1.1(2021-06-22) +- 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug +## 1.1.0(2021-06-22) +- 修复 只写setRules方法而导致校验不生效的Bug +- 修复 由上个办法引发的错误提示文字错位的Bug +## 1.0.48(2021-06-21) +- 修复 不设置 label 属性 ,无法设置label插槽的问题 +## 1.0.47(2021-06-21) +- 修复 不设置label属性,label-width属性不生效的bug +- 修复 setRules 方法与rules属性冲突的问题 +## 1.0.46(2021-06-04) +- 修复 动态删减数据导致报错的问题 +## 1.0.45(2021-06-04) +- 新增 modelValue 属性 ,value 即将废弃 +## 1.0.44(2021-06-02) +- 新增 uni-forms-item 可以设置单独的 rules +- 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤 +- 优化 submit 事件重命名为 validate +## 1.0.43(2021-05-12) +- 新增 组件示例地址 +## 1.0.42(2021-04-30) +- 修复 自定义检验器失效的问题 +## 1.0.41(2021-03-05) +- 更新 校验器 +- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug +## 1.0.40(2021-03-04) +- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug +## 1.0.39(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 校验器传入 int 等类型 ,返回String类型的Bug diff --git a/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue new file mode 100644 index 00000000..b3d42a26 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue @@ -0,0 +1,627 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue new file mode 100644 index 00000000..44095dd8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue @@ -0,0 +1,397 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/utils.js b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/utils.js new file mode 100644 index 00000000..6da24216 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/utils.js @@ -0,0 +1,293 @@ +/** + * 简单处理对象拷贝 + * @param {Obejct} 被拷贝对象 + * @@return {Object} 拷贝对象 + */ +export const deepCopy = (val) => { + return JSON.parse(JSON.stringify(val)) +} +/** + * 过滤数字类型 + * @param {String} format 数字类型 + * @@return {Boolean} 返回是否为数字类型 + */ +export const typeFilter = (format) => { + return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp'; +} + +/** + * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined + * @param {String} key 字段名 + * @param {any} value 字段值 + * @param {Object} rules 表单校验规则 + */ +export const getValue = (key, value, rules) => { + const isRuleNumType = rules.find(val => val.format && typeFilter(val.format)); + const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool'); + // 输入类型为 number + if (!!isRuleNumType) { + if (!value && value !== 0) { + value = null + } else { + value = isNumber(Number(value)) ? Number(value) : value + } + } + + // 输入类型为 boolean + if (!!isRuleBoolType) { + value = isBoolean(value) ? value : false + } + + return value; +} + +/** + * 获取表单数据 + * @param {String|Array} name 真实名称,需要使用 realName 获取 + * @param {Object} data 原始数据 + * @param {any} value 需要设置的值 + */ +export const setDataValue = (field, formdata, value) => { + formdata[field] = value + return value || '' +} + +/** + * 获取表单数据 + * @param {String|Array} field 真实名称,需要使用 realName 获取 + * @param {Object} data 原始数据 + */ +export const getDataValue = (field, data) => { + return objGet(data, field) +} + +/** + * 获取表单类型 + * @param {String|Array} field 真实名称,需要使用 realName 获取 + */ +export const getDataValueType = (field, data) => { + const value = getDataValue(field, data) + return { + type: type(value), + value + } +} + +/** + * 获取表单可用的真实name + * @param {String|Array} name 表单name + * @@return {String} 表单可用的真实name + */ +export const realName = (name, data = {}) => { + const base_name = _basePath(name) + if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) { + const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_') + return realname + } + return base_name[0] || name +} + +/** + * 判断是否表单可用的真实name + * @param {String|Array} name 表单name + * @@return {String} 表单可用的真实name + */ +export const isRealName = (name) => { + const reg = /^_formdata_#*/ + return reg.test(name) +} + +/** + * 获取表单数据的原始格式 + * @@return {Object|Array} object 需要解析的数据 + */ +export const rawData = (object = {}, name) => { + let newData = JSON.parse(JSON.stringify(object)) + let formData = {} + for(let i in newData){ + let path = name2arr(i) + objSet(formData,path,newData[i]) + } + return formData +} + +/** + * 真实name还原为 array + * @param {*} name + */ +export const name2arr = (name) => { + let field = name.replace('_formdata_#', '') + field = field.split('#').map(v => (isNumber(v) ? Number(v) : v)) + return field +} + +/** + * 对象中设置值 + * @param {Object|Array} object 源数据 + * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c'] + * @param {String} value 需要设置的值 + */ +export const objSet = (object, path, value) => { + if (typeof object !== 'object') return object; + _basePath(path).reduce((o, k, i, _) => { + if (i === _.length - 1) { + // 若遍历结束直接赋值 + o[k] = value + return null + } else if (k in o) { + // 若存在对应路径,则返回找到的对象,进行下一次遍历 + return o[k] + } else { + // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象 + o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {} + return o[k] + } + }, object) + // 返回object + return object; +} + +// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用 +function _basePath(path) { + // 若是数组,则直接返回 + if (Array.isArray(path)) return path + // 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']' + return path.replace(/\[/g, '.').replace(/\]/g, '').split('.') +} + +/** + * 从对象中获取值 + * @param {Object|Array} object 源数据 + * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c'] + * @param {String} defaultVal 如果无法从调用链中获取值的默认值 + */ +export const objGet = (object, path, defaultVal = 'undefined') => { + // 先将path处理成统一格式 + let newPath = _basePath(path) + // 递归处理,返回最后结果 + let val = newPath.reduce((o, k) => { + return (o || {})[k] + }, object); + return !val || val !== undefined ? val : defaultVal +} + + +/** + * 是否为 number 类型 + * @param {any} num 需要判断的值 + * @return {Boolean} 是否为 number + */ +export const isNumber = (num) => { + return !isNaN(Number(num)) +} + +/** + * 是否为 boolean 类型 + * @param {any} bool 需要判断的值 + * @return {Boolean} 是否为 boolean + */ +export const isBoolean = (bool) => { + return (typeof bool === 'boolean') +} +/** + * 是否有必填字段 + * @param {Object} rules 规则 + * @return {Boolean} 是否有必填字段 + */ +export const isRequiredField = (rules) => { + let isNoField = false; + for (let i = 0; i < rules.length; i++) { + const ruleData = rules[i]; + if (ruleData.required) { + isNoField = true; + break; + } + } + return isNoField; +} + + +/** + * 获取数据类型 + * @param {Any} obj 需要获取数据类型的值 + */ +export const type = (obj) => { + var class2type = {}; + + // 生成class2type映射 + "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) { + class2type["[object " + item + "]"] = item.toLowerCase(); + }) + if (obj == null) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[Object.prototype.toString.call(obj)] || "object" : + typeof obj; +} + +/** + * 判断两个值是否相等 + * @param {any} a 值 + * @param {any} b 值 + * @return {Boolean} 是否相等 + */ +export const isEqual = (a, b) => { + //如果a和b本来就全等 + if (a === b) { + //判断是否为0和-0 + return a !== 0 || 1 / a === 1 / b; + } + //判断是否为null和undefined + if (a == null || b == null) { + return a === b; + } + //接下来判断a和b的数据类型 + var classNameA = toString.call(a), + classNameB = toString.call(b); + //如果数据类型不相等,则返回false + if (classNameA !== classNameB) { + return false; + } + //如果数据类型相等,再根据不同数据类型分别判断 + switch (classNameA) { + case '[object RegExp]': + case '[object String]': + //进行字符串转换比较 + return '' + a === '' + b; + case '[object Number]': + //进行数字转换比较,判断是否为NaN + if (+a !== +a) { + return +b !== +b; + } + //判断是否为0或-0 + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + return +a === +b; + } + //如果是对象类型 + if (classNameA == '[object Object]') { + //获取a和b的属性长度 + var propsA = Object.getOwnPropertyNames(a), + propsB = Object.getOwnPropertyNames(b); + if (propsA.length != propsB.length) { + return false; + } + for (var i = 0; i < propsA.length; i++) { + var propName = propsA[i]; + //如果对应属性对应值不相等,则返回false + if (a[propName] !== b[propName]) { + return false; + } + } + return true; + } + //如果是数组类型 + if (classNameA == '[object Array]') { + if (a.toString() == b.toString()) { + return true; + } + return false; + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/validate.js b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/validate.js new file mode 100644 index 00000000..1834c6cf --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/components/uni-forms/validate.js @@ -0,0 +1,486 @@ +var pattern = { + email: /^\S+?@\S+?\.\S+?$/, + idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, + url: new RegExp( + "^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$", + 'i') +}; + +const FORMAT_MAPPING = { + "int": 'integer', + "bool": 'boolean', + "double": 'number', + "long": 'number', + "password": 'string' + // "fileurls": 'array' +} + +function formatMessage(args, resources = '') { + var defaultMessage = ['label'] + defaultMessage.forEach((item) => { + if (args[item] === undefined) { + args[item] = '' + } + }) + + let str = resources + for (let key in args) { + let reg = new RegExp('{' + key + '}') + str = str.replace(reg, args[key]) + } + return str +} + +function isEmptyValue(value, type) { + if (value === undefined || value === null) { + return true; + } + + if (typeof value === 'string' && !value) { + return true; + } + + if (Array.isArray(value) && !value.length) { + return true; + } + + if (type === 'object' && !Object.keys(value).length) { + return true; + } + + return false; +} + +const types = { + integer(value) { + return types.number(value) && parseInt(value, 10) === value; + }, + string(value) { + return typeof value === 'string'; + }, + number(value) { + if (isNaN(value)) { + return false; + } + return typeof value === 'number'; + }, + "boolean": function(value) { + return typeof value === 'boolean'; + }, + "float": function(value) { + return types.number(value) && !types.integer(value); + }, + array(value) { + return Array.isArray(value); + }, + object(value) { + return typeof value === 'object' && !types.array(value); + }, + date(value) { + return value instanceof Date; + }, + timestamp(value) { + if (!this.integer(value) || Math.abs(value).toString().length > 16) { + return false + } + return true; + }, + file(value) { + return typeof value.url === 'string'; + }, + email(value) { + return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255; + }, + url(value) { + return typeof value === 'string' && !!value.match(pattern.url); + }, + pattern(reg, value) { + try { + return new RegExp(reg).test(value); + } catch (e) { + return false; + } + }, + method(value) { + return typeof value === 'function'; + }, + idcard(value) { + return typeof value === 'string' && !!value.match(pattern.idcard); + }, + 'url-https'(value) { + return this.url(value) && value.startsWith('https://'); + }, + 'url-scheme'(value) { + return value.startsWith('://'); + }, + 'url-web'(value) { + return false; + } +} + +class RuleValidator { + + constructor(message) { + this._message = message + } + + async validateRule(fieldKey, fieldValue, value, data, allData) { + var result = null + + let rules = fieldValue.rules + + let hasRequired = rules.findIndex((item) => { + return item.required + }) + if (hasRequired < 0) { + if (value === null || value === undefined) { + return result + } + if (typeof value === 'string' && !value.length) { + return result + } + } + + var message = this._message + + if (rules === undefined) { + return message['default'] + } + + for (var i = 0; i < rules.length; i++) { + let rule = rules[i] + let vt = this._getValidateType(rule) + + Object.assign(rule, { + label: fieldValue.label || `["${fieldKey}"]` + }) + + if (RuleValidatorHelper[vt]) { + result = RuleValidatorHelper[vt](rule, value, message) + if (result != null) { + break + } + } + + if (rule.validateExpr) { + let now = Date.now() + let resultExpr = rule.validateExpr(value, allData, now) + if (resultExpr === false) { + result = this._getMessage(rule, rule.errorMessage || this._message['default']) + break + } + } + + if (rule.validateFunction) { + result = await this.validateFunction(rule, value, data, allData, vt) + if (result !== null) { + break + } + } + } + + if (result !== null) { + result = message.TAG + result + } + + return result + } + + async validateFunction(rule, value, data, allData, vt) { + let result = null + try { + let callbackMessage = null + const res = await rule.validateFunction(rule, value, allData || data, (message) => { + callbackMessage = message + }) + if (callbackMessage || (typeof res === 'string' && res) || res === false) { + result = this._getMessage(rule, callbackMessage || res, vt) + } + } catch (e) { + result = this._getMessage(rule, e.message, vt) + } + return result + } + + _getMessage(rule, message, vt) { + return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default']) + } + + _getValidateType(rule) { + var result = '' + if (rule.required) { + result = 'required' + } else if (rule.format) { + result = 'format' + } else if (rule.arrayType) { + result = 'arrayTypeFormat' + } else if (rule.range) { + result = 'range' + } else if (rule.maximum !== undefined || rule.minimum !== undefined) { + result = 'rangeNumber' + } else if (rule.maxLength !== undefined || rule.minLength !== undefined) { + result = 'rangeLength' + } else if (rule.pattern) { + result = 'pattern' + } else if (rule.validateFunction) { + result = 'validateFunction' + } + return result + } +} + +const RuleValidatorHelper = { + required(rule, value, message) { + if (rule.required && isEmptyValue(value, rule.format || typeof value)) { + return formatMessage(rule, rule.errorMessage || message.required); + } + + return null + }, + + range(rule, value, message) { + const { + range, + errorMessage + } = rule; + + let list = new Array(range.length); + for (let i = 0; i < range.length; i++) { + const item = range[i]; + if (types.object(item) && item.value !== undefined) { + list[i] = item.value; + } else { + list[i] = item; + } + } + + let result = false + if (Array.isArray(value)) { + result = (new Set(value.concat(list)).size === list.length); + } else { + if (list.indexOf(value) > -1) { + result = true; + } + } + + if (!result) { + return formatMessage(rule, errorMessage || message['enum']); + } + + return null + }, + + rangeNumber(rule, value, message) { + if (!types.number(value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + let { + minimum, + maximum, + exclusiveMinimum, + exclusiveMaximum + } = rule; + let min = exclusiveMinimum ? value <= minimum : value < minimum; + let max = exclusiveMaximum ? value >= maximum : value > maximum; + + if (minimum !== undefined && min) { + return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ? + 'exclusiveMinimum' : 'minimum' + ]) + } else if (maximum !== undefined && max) { + return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ? + 'exclusiveMaximum' : 'maximum' + ]) + } else if (minimum !== undefined && maximum !== undefined && (min || max)) { + return formatMessage(rule, rule.errorMessage || message['number'].range) + } + + return null + }, + + rangeLength(rule, value, message) { + if (!types.string(value) && !types.array(value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + let min = rule.minLength; + let max = rule.maxLength; + let val = value.length; + + if (min !== undefined && val < min) { + return formatMessage(rule, rule.errorMessage || message['length'].minLength) + } else if (max !== undefined && val > max) { + return formatMessage(rule, rule.errorMessage || message['length'].maxLength) + } else if (min !== undefined && max !== undefined && (val < min || val > max)) { + return formatMessage(rule, rule.errorMessage || message['length'].range) + } + + return null + }, + + pattern(rule, value, message) { + if (!types['pattern'](rule.pattern, value)) { + return formatMessage(rule, rule.errorMessage || message.pattern.mismatch); + } + + return null + }, + + format(rule, value, message) { + var customTypes = Object.keys(types); + var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType); + + if (customTypes.indexOf(format) > -1) { + if (!types[format](value)) { + return formatMessage(rule, rule.errorMessage || message.typeError); + } + } + + return null + }, + + arrayTypeFormat(rule, value, message) { + if (!Array.isArray(value)) { + return formatMessage(rule, rule.errorMessage || message.typeError); + } + + for (let i = 0; i < value.length; i++) { + const element = value[i]; + let formatResult = this.format(rule, element, message) + if (formatResult !== null) { + return formatResult + } + } + + return null + } +} + +class SchemaValidator extends RuleValidator { + + constructor(schema, options) { + super(SchemaValidator.message); + + this._schema = schema + this._options = options || null + } + + updateSchema(schema) { + this._schema = schema + } + + async validate(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidate(data, false, allData) + } + return result.length ? result[0] : null + } + + async validateAll(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidate(data, true, allData) + } + return result + } + + async validateUpdate(data, allData) { + let result = this._checkFieldInSchema(data) + if (!result) { + result = await this.invokeValidateUpdate(data, false, allData) + } + return result.length ? result[0] : null + } + + async invokeValidate(data, all, allData) { + let result = [] + let schema = this._schema + for (let key in schema) { + let value = schema[key] + let errorMessage = await this.validateRule(key, value, data[key], data, allData) + if (errorMessage != null) { + result.push({ + key, + errorMessage + }) + if (!all) break + } + } + return result + } + + async invokeValidateUpdate(data, all, allData) { + let result = [] + for (let key in data) { + let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData) + if (errorMessage != null) { + result.push({ + key, + errorMessage + }) + if (!all) break + } + } + return result + } + + _checkFieldInSchema(data) { + var keys = Object.keys(data) + var keys2 = Object.keys(this._schema) + if (new Set(keys.concat(keys2)).size === keys2.length) { + return '' + } + + var noExistFields = keys.filter((key) => { + return keys2.indexOf(key) < 0; + }) + var errorMessage = formatMessage({ + field: JSON.stringify(noExistFields) + }, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid']) + return [{ + key: 'invalid', + errorMessage + }] + } +} + +function Message() { + return { + TAG: "", + default: '验证错误', + defaultInvalid: '提交的字段{field}在数据库中并不存在', + validateFunction: '验证无效', + required: '{label}必填', + 'enum': '{label}超出范围', + timestamp: '{label}格式无效', + whitespace: '{label}不能为空', + typeError: '{label}类型无效', + date: { + format: '{label}日期{value}格式无效', + parse: '{label}日期无法解析,{value}无效', + invalid: '{label}日期{value}无效' + }, + length: { + minLength: '{label}长度不能少于{minLength}', + maxLength: '{label}长度不能超过{maxLength}', + range: '{label}必须介于{minLength}和{maxLength}之间' + }, + number: { + minimum: '{label}不能小于{minimum}', + maximum: '{label}不能大于{maximum}', + exclusiveMinimum: '{label}不能小于等于{minimum}', + exclusiveMaximum: '{label}不能大于等于{maximum}', + range: '{label}必须介于{minimum}and{maximum}之间' + }, + pattern: { + mismatch: '{label}格式不匹配' + } + }; +} + + +SchemaValidator.message = new Message(); + +export default SchemaValidator diff --git a/yanzhu-ui-app/uni_modules/uni-forms/package.json b/yanzhu-ui-app/uni_modules/uni-forms/package.json new file mode 100644 index 00000000..19256114 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-forms", + "displayName": "uni-forms 表单", + "version": "1.4.9", + "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据", + "keywords": [ + "uni-ui", + "表单", + "校验", + "表单校验", + "表单验证" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-forms/readme.md b/yanzhu-ui-app/uni_modules/uni-forms/readme.md new file mode 100644 index 00000000..63d5a043 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-forms/readme.md @@ -0,0 +1,23 @@ + + +## Forms 表单 + +> **组件名:uni-forms** +> 代码块: `uForms`、`uni-forms-item` +> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。 + + +uni-app的内置组件已经有了 `

`组件,用于提交表单内容。 + +然而几乎每个表单都需要做表单验证,为了方便做表单验证,减少重复开发,`uni ui` 又基于 ``组件封装了 ``组件,内置了表单验证功能。 + +`` 提供了 `rules`属性来描述校验规则、``子组件来包裹具体的表单项,以及给原生或三方组件提供了 `binddata()` 来设置表单值。 + +每个要校验的表单项,不管input还是checkbox,都必须放在``组件中,且一个``组件只能放置一个表单项。 + +``组件内部预留了显示error message的区域,默认是在表单项的底部。 + +另外,``组件下面的各个表单项,可以通过``包裹为不同的分组。同一``下的不同表单项目将聚拢在一起,同其他group保持垂直间距。``仅影响视觉效果。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-forms) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/changelog.md b/yanzhu-ui-app/uni_modules/uni-goods-nav/changelog.md new file mode 100644 index 00000000..c6264c67 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/changelog.md @@ -0,0 +1,18 @@ +## 1.2.1(2022-05-30) +- 新增 stat属性,是否开启uni统计功能 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-goods-nav](https://uniapp.dcloud.io/component/uniui/uni-goods-nav) +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json new file mode 100644 index 00000000..dcdba41c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "shop", + "uni-goods-nav.options.cart": "cart", + "uni-goods-nav.buttonGroup.addToCart": "add to cart", + "uni-goods-nav.buttonGroup.buyNow": "buy now" +} diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json new file mode 100644 index 00000000..48ee344c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "店铺", + "uni-goods-nav.options.cart": "购物车", + "uni-goods-nav.buttonGroup.addToCart": "加入购物车", + "uni-goods-nav.buttonGroup.buyNow": "立即购买" +} diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json new file mode 100644 index 00000000..d0a0255c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json @@ -0,0 +1,6 @@ +{ + "uni-goods-nav.options.shop": "店鋪", + "uni-goods-nav.options.cart": "購物車", + "uni-goods-nav.buttonGroup.addToCart": "加入購物車", + "uni-goods-nav.buttonGroup.buyNow": "立即購買" +} diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue new file mode 100644 index 00000000..8a16b175 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue @@ -0,0 +1,229 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/package.json b/yanzhu-ui-app/uni_modules/uni-goods-nav/package.json new file mode 100644 index 00000000..636e45e7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-goods-nav", + "displayName": "uni-goods-nav 商品导航", + "version": "1.2.1", + "description": "商品导航组件主要用于电商类应用底部导航,可自定义加入购物车,购买等操作", + "keywords": [ + "uni-ui", + "uniui", + "商品导航" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-goods-nav/readme.md b/yanzhu-ui-app/uni_modules/uni-goods-nav/readme.md new file mode 100644 index 00000000..07df93f5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-goods-nav/readme.md @@ -0,0 +1,10 @@ + + +## GoodsNav 商品导航 +> **组件名:uni-goods-nav** +> 代码块: `uGoodsNav` + +商品加入购物车,立即购买等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-goods-nav) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-grid/changelog.md b/yanzhu-ui-app/uni_modules/uni-grid/changelog.md new file mode 100644 index 00000000..d301166c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-grid/changelog.md @@ -0,0 +1,13 @@ +## 1.4.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-grid](https://uniapp.dcloud.io/component/uniui/uni-grid) +## 1.3.2(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.3.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.3.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.2.4(2021-05-12) +- 新增 组件示例地址 +## 1.2.3(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue b/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue new file mode 100644 index 00000000..20fd54e5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue b/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue new file mode 100644 index 00000000..96a412f6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-grid/package.json b/yanzhu-ui-app/uni_modules/uni-grid/package.json new file mode 100644 index 00000000..ccb2c917 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-grid/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-grid", + "displayName": "uni-grid 宫格", + "version": "1.4.0", + "description": "Grid 宫格组件,提供移动端常见的宫格布局,如九宫格。", + "keywords": [ + "uni-ui", + "uniui", + "九宫格", + "表格" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-grid/readme.md b/yanzhu-ui-app/uni_modules/uni-grid/readme.md new file mode 100644 index 00000000..0aa44cc1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-grid/readme.md @@ -0,0 +1,11 @@ + + +## Grid 宫格 +> **组件名:uni-grid** +> 代码块: `uGrid` + + +宫格组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-grid) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-group/changelog.md b/yanzhu-ui-app/uni_modules/uni-group/changelog.md new file mode 100644 index 00000000..a7024fdf --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-group/changelog.md @@ -0,0 +1,16 @@ +## 1.2.2(2022-05-30) +- 新增 stat属性,是否开启uni统计功能 +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-group](https://uniapp.dcloud.io/component/uniui/uni-group) +## 1.1.7(2021-11-08) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- 优化 组件文档 +## 1.0.3(2021-05-12) +- 新增 组件示例地址 +## 1.0.2(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 兼容 nvue 页面 diff --git a/yanzhu-ui-app/uni_modules/uni-group/components/uni-group/uni-group.vue b/yanzhu-ui-app/uni_modules/uni-group/components/uni-group/uni-group.vue new file mode 100644 index 00000000..3425ecd3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-group/components/uni-group/uni-group.vue @@ -0,0 +1,134 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-group/package.json b/yanzhu-ui-app/uni_modules/uni-group/package.json new file mode 100644 index 00000000..ea00a08c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-group/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-group", + "displayName": "uni-group 分组", + "version": "1.2.2", + "description": "分组组件可用于将组件用于分组,添加间隔,以产生明显的区块", + "keywords": [ + "uni-ui", + "uniui", + "group", + "分组", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-group/readme.md b/yanzhu-ui-app/uni_modules/uni-group/readme.md new file mode 100644 index 00000000..bae67f46 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-group/readme.md @@ -0,0 +1,9 @@ + +## Group 分组 +> **组件名:uni-group** +> 代码块: `uGroup` + +分组组件可用于将组件分组,添加间隔,以产生明显的区块。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-group) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-icons/changelog.md b/yanzhu-ui-app/uni_modules/uni-icons/changelog.md new file mode 100644 index 00000000..64498853 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-icons/changelog.md @@ -0,0 +1,22 @@ +## 1.3.5(2022-01-24) +- 优化 size 属性可以传入不带单位的字符串数值 +## 1.3.4(2022-01-24) +- 优化 size 支持其他单位 +## 1.3.3(2022-01-17) +- 修复 nvue 有些图标不显示的bug,兼容老版本图标 +## 1.3.2(2021-12-01) +- 优化 示例可复制图标名称 +## 1.3.1(2021-11-23) +- 优化 兼容旧组件 type 值 +## 1.3.0(2021-11-19) +- 新增 更多图标 +- 优化 自定义图标使用方式 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons) +## 1.1.7(2021-11-08) +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.5(2021-05-12) +- 新增 组件示例地址 +## 1.1.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/icons.js b/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/icons.js new file mode 100644 index 00000000..78899364 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/icons.js @@ -0,0 +1,1169 @@ +export default { + "id": "2852637", + "name": "uniui图标库", + "font_family": "uniicons", + "css_prefix_text": "uniui-", + "description": "", + "glyphs": [ + { + "icon_id": "25027049", + "name": "yanse", + "font_class": "color", + "unicode": "e6cf", + "unicode_decimal": 59087 + }, + { + "icon_id": "25027048", + "name": "wallet", + "font_class": "wallet", + "unicode": "e6b1", + "unicode_decimal": 59057 + }, + { + "icon_id": "25015720", + "name": "settings-filled", + "font_class": "settings-filled", + "unicode": "e6ce", + "unicode_decimal": 59086 + }, + { + "icon_id": "25015434", + "name": "shimingrenzheng-filled", + "font_class": "auth-filled", + "unicode": "e6cc", + "unicode_decimal": 59084 + }, + { + "icon_id": "24934246", + "name": "shop-filled", + "font_class": "shop-filled", + "unicode": "e6cd", + "unicode_decimal": 59085 + }, + { + "icon_id": "24934159", + "name": "staff-filled-01", + "font_class": "staff-filled", + "unicode": "e6cb", + "unicode_decimal": 59083 + }, + { + "icon_id": "24932461", + "name": "VIP-filled", + "font_class": "vip-filled", + "unicode": "e6c6", + "unicode_decimal": 59078 + }, + { + "icon_id": "24932462", + "name": "plus_circle_fill", + "font_class": "plus-filled", + "unicode": "e6c7", + "unicode_decimal": 59079 + }, + { + "icon_id": "24932463", + "name": "folder_add-filled", + "font_class": "folder-add-filled", + "unicode": "e6c8", + "unicode_decimal": 59080 + }, + { + "icon_id": "24932464", + "name": "yanse-filled", + "font_class": "color-filled", + "unicode": "e6c9", + "unicode_decimal": 59081 + }, + { + "icon_id": "24932465", + "name": "tune-filled", + "font_class": "tune-filled", + "unicode": "e6ca", + "unicode_decimal": 59082 + }, + { + "icon_id": "24932455", + "name": "a-rilidaka-filled", + "font_class": "calendar-filled", + "unicode": "e6c0", + "unicode_decimal": 59072 + }, + { + "icon_id": "24932456", + "name": "notification-filled", + "font_class": "notification-filled", + "unicode": "e6c1", + "unicode_decimal": 59073 + }, + { + "icon_id": "24932457", + "name": "wallet-filled", + "font_class": "wallet-filled", + "unicode": "e6c2", + "unicode_decimal": 59074 + }, + { + "icon_id": "24932458", + "name": "paihangbang-filled", + "font_class": "medal-filled", + "unicode": "e6c3", + "unicode_decimal": 59075 + }, + { + "icon_id": "24932459", + "name": "gift-filled", + "font_class": "gift-filled", + "unicode": "e6c4", + "unicode_decimal": 59076 + }, + { + "icon_id": "24932460", + "name": "fire-filled", + "font_class": "fire-filled", + "unicode": "e6c5", + "unicode_decimal": 59077 + }, + { + "icon_id": "24928001", + "name": "refreshempty", + "font_class": "refreshempty", + "unicode": "e6bf", + "unicode_decimal": 59071 + }, + { + "icon_id": "24926853", + "name": "location-ellipse", + "font_class": "location-filled", + "unicode": "e6af", + "unicode_decimal": 59055 + }, + { + "icon_id": "24926735", + "name": "person-filled", + "font_class": "person-filled", + "unicode": "e69d", + "unicode_decimal": 59037 + }, + { + "icon_id": "24926703", + "name": "personadd-filled", + "font_class": "personadd-filled", + "unicode": "e698", + "unicode_decimal": 59032 + }, + { + "icon_id": "24923351", + "name": "back", + "font_class": "back", + "unicode": "e6b9", + "unicode_decimal": 59065 + }, + { + "icon_id": "24923352", + "name": "forward", + "font_class": "forward", + "unicode": "e6ba", + "unicode_decimal": 59066 + }, + { + "icon_id": "24923353", + "name": "arrowthinright", + "font_class": "arrow-right", + "unicode": "e6bb", + "unicode_decimal": 59067 + }, + { + "icon_id": "24923353", + "name": "arrowthinright", + "font_class": "arrowthinright", + "unicode": "e6bb", + "unicode_decimal": 59067 + }, + { + "icon_id": "24923354", + "name": "arrowthinleft", + "font_class": "arrow-left", + "unicode": "e6bc", + "unicode_decimal": 59068 + }, + { + "icon_id": "24923354", + "name": "arrowthinleft", + "font_class": "arrowthinleft", + "unicode": "e6bc", + "unicode_decimal": 59068 + }, + { + "icon_id": "24923355", + "name": "arrowthinup", + "font_class": "arrow-up", + "unicode": "e6bd", + "unicode_decimal": 59069 + }, + { + "icon_id": "24923355", + "name": "arrowthinup", + "font_class": "arrowthinup", + "unicode": "e6bd", + "unicode_decimal": 59069 + }, + { + "icon_id": "24923356", + "name": "arrowthindown", + "font_class": "arrow-down", + "unicode": "e6be", + "unicode_decimal": 59070 + },{ + "icon_id": "24923356", + "name": "arrowthindown", + "font_class": "arrowthindown", + "unicode": "e6be", + "unicode_decimal": 59070 + }, + { + "icon_id": "24923349", + "name": "arrowdown", + "font_class": "bottom", + "unicode": "e6b8", + "unicode_decimal": 59064 + },{ + "icon_id": "24923349", + "name": "arrowdown", + "font_class": "arrowdown", + "unicode": "e6b8", + "unicode_decimal": 59064 + }, + { + "icon_id": "24923346", + "name": "arrowright", + "font_class": "right", + "unicode": "e6b5", + "unicode_decimal": 59061 + }, + { + "icon_id": "24923346", + "name": "arrowright", + "font_class": "arrowright", + "unicode": "e6b5", + "unicode_decimal": 59061 + }, + { + "icon_id": "24923347", + "name": "arrowup", + "font_class": "top", + "unicode": "e6b6", + "unicode_decimal": 59062 + }, + { + "icon_id": "24923347", + "name": "arrowup", + "font_class": "arrowup", + "unicode": "e6b6", + "unicode_decimal": 59062 + }, + { + "icon_id": "24923348", + "name": "arrowleft", + "font_class": "left", + "unicode": "e6b7", + "unicode_decimal": 59063 + }, + { + "icon_id": "24923348", + "name": "arrowleft", + "font_class": "arrowleft", + "unicode": "e6b7", + "unicode_decimal": 59063 + }, + { + "icon_id": "24923334", + "name": "eye", + "font_class": "eye", + "unicode": "e651", + "unicode_decimal": 58961 + }, + { + "icon_id": "24923335", + "name": "eye-filled", + "font_class": "eye-filled", + "unicode": "e66a", + "unicode_decimal": 58986 + }, + { + "icon_id": "24923336", + "name": "eye-slash", + "font_class": "eye-slash", + "unicode": "e6b3", + "unicode_decimal": 59059 + }, + { + "icon_id": "24923337", + "name": "eye-slash-filled", + "font_class": "eye-slash-filled", + "unicode": "e6b4", + "unicode_decimal": 59060 + }, + { + "icon_id": "24923305", + "name": "info-filled", + "font_class": "info-filled", + "unicode": "e649", + "unicode_decimal": 58953 + }, + { + "icon_id": "24923299", + "name": "reload-01", + "font_class": "reload", + "unicode": "e6b2", + "unicode_decimal": 59058 + }, + { + "icon_id": "24923195", + "name": "mic_slash_fill", + "font_class": "micoff-filled", + "unicode": "e6b0", + "unicode_decimal": 59056 + }, + { + "icon_id": "24923165", + "name": "map-pin-ellipse", + "font_class": "map-pin-ellipse", + "unicode": "e6ac", + "unicode_decimal": 59052 + }, + { + "icon_id": "24923166", + "name": "map-pin", + "font_class": "map-pin", + "unicode": "e6ad", + "unicode_decimal": 59053 + }, + { + "icon_id": "24923167", + "name": "location", + "font_class": "location", + "unicode": "e6ae", + "unicode_decimal": 59054 + }, + { + "icon_id": "24923064", + "name": "starhalf", + "font_class": "starhalf", + "unicode": "e683", + "unicode_decimal": 59011 + }, + { + "icon_id": "24923065", + "name": "star", + "font_class": "star", + "unicode": "e688", + "unicode_decimal": 59016 + }, + { + "icon_id": "24923066", + "name": "star-filled", + "font_class": "star-filled", + "unicode": "e68f", + "unicode_decimal": 59023 + }, + { + "icon_id": "24899646", + "name": "a-rilidaka", + "font_class": "calendar", + "unicode": "e6a0", + "unicode_decimal": 59040 + }, + { + "icon_id": "24899647", + "name": "fire", + "font_class": "fire", + "unicode": "e6a1", + "unicode_decimal": 59041 + }, + { + "icon_id": "24899648", + "name": "paihangbang", + "font_class": "medal", + "unicode": "e6a2", + "unicode_decimal": 59042 + }, + { + "icon_id": "24899649", + "name": "font", + "font_class": "font", + "unicode": "e6a3", + "unicode_decimal": 59043 + }, + { + "icon_id": "24899650", + "name": "gift", + "font_class": "gift", + "unicode": "e6a4", + "unicode_decimal": 59044 + }, + { + "icon_id": "24899651", + "name": "link", + "font_class": "link", + "unicode": "e6a5", + "unicode_decimal": 59045 + }, + { + "icon_id": "24899652", + "name": "notification", + "font_class": "notification", + "unicode": "e6a6", + "unicode_decimal": 59046 + }, + { + "icon_id": "24899653", + "name": "staff", + "font_class": "staff", + "unicode": "e6a7", + "unicode_decimal": 59047 + }, + { + "icon_id": "24899654", + "name": "VIP", + "font_class": "vip", + "unicode": "e6a8", + "unicode_decimal": 59048 + }, + { + "icon_id": "24899655", + "name": "folder_add", + "font_class": "folder-add", + "unicode": "e6a9", + "unicode_decimal": 59049 + }, + { + "icon_id": "24899656", + "name": "tune", + "font_class": "tune", + "unicode": "e6aa", + "unicode_decimal": 59050 + }, + { + "icon_id": "24899657", + "name": "shimingrenzheng", + "font_class": "auth", + "unicode": "e6ab", + "unicode_decimal": 59051 + }, + { + "icon_id": "24899565", + "name": "person", + "font_class": "person", + "unicode": "e699", + "unicode_decimal": 59033 + }, + { + "icon_id": "24899566", + "name": "email-filled", + "font_class": "email-filled", + "unicode": "e69a", + "unicode_decimal": 59034 + }, + { + "icon_id": "24899567", + "name": "phone-filled", + "font_class": "phone-filled", + "unicode": "e69b", + "unicode_decimal": 59035 + }, + { + "icon_id": "24899568", + "name": "phone", + "font_class": "phone", + "unicode": "e69c", + "unicode_decimal": 59036 + }, + { + "icon_id": "24899570", + "name": "email", + "font_class": "email", + "unicode": "e69e", + "unicode_decimal": 59038 + }, + { + "icon_id": "24899571", + "name": "personadd", + "font_class": "personadd", + "unicode": "e69f", + "unicode_decimal": 59039 + }, + { + "icon_id": "24899558", + "name": "chatboxes-filled", + "font_class": "chatboxes-filled", + "unicode": "e692", + "unicode_decimal": 59026 + }, + { + "icon_id": "24899559", + "name": "contact", + "font_class": "contact", + "unicode": "e693", + "unicode_decimal": 59027 + }, + { + "icon_id": "24899560", + "name": "chatbubble-filled", + "font_class": "chatbubble-filled", + "unicode": "e694", + "unicode_decimal": 59028 + }, + { + "icon_id": "24899561", + "name": "contact-filled", + "font_class": "contact-filled", + "unicode": "e695", + "unicode_decimal": 59029 + }, + { + "icon_id": "24899562", + "name": "chatboxes", + "font_class": "chatboxes", + "unicode": "e696", + "unicode_decimal": 59030 + }, + { + "icon_id": "24899563", + "name": "chatbubble", + "font_class": "chatbubble", + "unicode": "e697", + "unicode_decimal": 59031 + }, + { + "icon_id": "24881290", + "name": "upload-filled", + "font_class": "upload-filled", + "unicode": "e68e", + "unicode_decimal": 59022 + }, + { + "icon_id": "24881292", + "name": "upload", + "font_class": "upload", + "unicode": "e690", + "unicode_decimal": 59024 + }, + { + "icon_id": "24881293", + "name": "weixin", + "font_class": "weixin", + "unicode": "e691", + "unicode_decimal": 59025 + }, + { + "icon_id": "24881274", + "name": "compose", + "font_class": "compose", + "unicode": "e67f", + "unicode_decimal": 59007 + }, + { + "icon_id": "24881275", + "name": "qq", + "font_class": "qq", + "unicode": "e680", + "unicode_decimal": 59008 + }, + { + "icon_id": "24881276", + "name": "download-filled", + "font_class": "download-filled", + "unicode": "e681", + "unicode_decimal": 59009 + }, + { + "icon_id": "24881277", + "name": "pengyouquan", + "font_class": "pyq", + "unicode": "e682", + "unicode_decimal": 59010 + }, + { + "icon_id": "24881279", + "name": "sound", + "font_class": "sound", + "unicode": "e684", + "unicode_decimal": 59012 + }, + { + "icon_id": "24881280", + "name": "trash-filled", + "font_class": "trash-filled", + "unicode": "e685", + "unicode_decimal": 59013 + }, + { + "icon_id": "24881281", + "name": "sound-filled", + "font_class": "sound-filled", + "unicode": "e686", + "unicode_decimal": 59014 + }, + { + "icon_id": "24881282", + "name": "trash", + "font_class": "trash", + "unicode": "e687", + "unicode_decimal": 59015 + }, + { + "icon_id": "24881284", + "name": "videocam-filled", + "font_class": "videocam-filled", + "unicode": "e689", + "unicode_decimal": 59017 + }, + { + "icon_id": "24881285", + "name": "spinner-cycle", + "font_class": "spinner-cycle", + "unicode": "e68a", + "unicode_decimal": 59018 + }, + { + "icon_id": "24881286", + "name": "weibo", + "font_class": "weibo", + "unicode": "e68b", + "unicode_decimal": 59019 + }, + { + "icon_id": "24881288", + "name": "videocam", + "font_class": "videocam", + "unicode": "e68c", + "unicode_decimal": 59020 + }, + { + "icon_id": "24881289", + "name": "download", + "font_class": "download", + "unicode": "e68d", + "unicode_decimal": 59021 + }, + { + "icon_id": "24879601", + "name": "help", + "font_class": "help", + "unicode": "e679", + "unicode_decimal": 59001 + }, + { + "icon_id": "24879602", + "name": "navigate-filled", + "font_class": "navigate-filled", + "unicode": "e67a", + "unicode_decimal": 59002 + }, + { + "icon_id": "24879603", + "name": "plusempty", + "font_class": "plusempty", + "unicode": "e67b", + "unicode_decimal": 59003 + }, + { + "icon_id": "24879604", + "name": "smallcircle", + "font_class": "smallcircle", + "unicode": "e67c", + "unicode_decimal": 59004 + }, + { + "icon_id": "24879605", + "name": "minus-filled", + "font_class": "minus-filled", + "unicode": "e67d", + "unicode_decimal": 59005 + }, + { + "icon_id": "24879606", + "name": "micoff", + "font_class": "micoff", + "unicode": "e67e", + "unicode_decimal": 59006 + }, + { + "icon_id": "24879588", + "name": "closeempty", + "font_class": "closeempty", + "unicode": "e66c", + "unicode_decimal": 58988 + }, + { + "icon_id": "24879589", + "name": "clear", + "font_class": "clear", + "unicode": "e66d", + "unicode_decimal": 58989 + }, + { + "icon_id": "24879590", + "name": "navigate", + "font_class": "navigate", + "unicode": "e66e", + "unicode_decimal": 58990 + }, + { + "icon_id": "24879591", + "name": "minus", + "font_class": "minus", + "unicode": "e66f", + "unicode_decimal": 58991 + }, + { + "icon_id": "24879592", + "name": "image", + "font_class": "image", + "unicode": "e670", + "unicode_decimal": 58992 + }, + { + "icon_id": "24879593", + "name": "mic", + "font_class": "mic", + "unicode": "e671", + "unicode_decimal": 58993 + }, + { + "icon_id": "24879594", + "name": "paperplane", + "font_class": "paperplane", + "unicode": "e672", + "unicode_decimal": 58994 + }, + { + "icon_id": "24879595", + "name": "close", + "font_class": "close", + "unicode": "e673", + "unicode_decimal": 58995 + }, + { + "icon_id": "24879596", + "name": "help-filled", + "font_class": "help-filled", + "unicode": "e674", + "unicode_decimal": 58996 + }, + { + "icon_id": "24879597", + "name": "plus-filled", + "font_class": "paperplane-filled", + "unicode": "e675", + "unicode_decimal": 58997 + }, + { + "icon_id": "24879598", + "name": "plus", + "font_class": "plus", + "unicode": "e676", + "unicode_decimal": 58998 + }, + { + "icon_id": "24879599", + "name": "mic-filled", + "font_class": "mic-filled", + "unicode": "e677", + "unicode_decimal": 58999 + }, + { + "icon_id": "24879600", + "name": "image-filled", + "font_class": "image-filled", + "unicode": "e678", + "unicode_decimal": 59000 + }, + { + "icon_id": "24855900", + "name": "locked-filled", + "font_class": "locked-filled", + "unicode": "e668", + "unicode_decimal": 58984 + }, + { + "icon_id": "24855901", + "name": "info", + "font_class": "info", + "unicode": "e669", + "unicode_decimal": 58985 + }, + { + "icon_id": "24855903", + "name": "locked", + "font_class": "locked", + "unicode": "e66b", + "unicode_decimal": 58987 + }, + { + "icon_id": "24855884", + "name": "camera-filled", + "font_class": "camera-filled", + "unicode": "e658", + "unicode_decimal": 58968 + }, + { + "icon_id": "24855885", + "name": "chat-filled", + "font_class": "chat-filled", + "unicode": "e659", + "unicode_decimal": 58969 + }, + { + "icon_id": "24855886", + "name": "camera", + "font_class": "camera", + "unicode": "e65a", + "unicode_decimal": 58970 + }, + { + "icon_id": "24855887", + "name": "circle", + "font_class": "circle", + "unicode": "e65b", + "unicode_decimal": 58971 + }, + { + "icon_id": "24855888", + "name": "checkmarkempty", + "font_class": "checkmarkempty", + "unicode": "e65c", + "unicode_decimal": 58972 + }, + { + "icon_id": "24855889", + "name": "chat", + "font_class": "chat", + "unicode": "e65d", + "unicode_decimal": 58973 + }, + { + "icon_id": "24855890", + "name": "circle-filled", + "font_class": "circle-filled", + "unicode": "e65e", + "unicode_decimal": 58974 + }, + { + "icon_id": "24855891", + "name": "flag", + "font_class": "flag", + "unicode": "e65f", + "unicode_decimal": 58975 + }, + { + "icon_id": "24855892", + "name": "flag-filled", + "font_class": "flag-filled", + "unicode": "e660", + "unicode_decimal": 58976 + }, + { + "icon_id": "24855893", + "name": "gear-filled", + "font_class": "gear-filled", + "unicode": "e661", + "unicode_decimal": 58977 + }, + { + "icon_id": "24855894", + "name": "home", + "font_class": "home", + "unicode": "e662", + "unicode_decimal": 58978 + }, + { + "icon_id": "24855895", + "name": "home-filled", + "font_class": "home-filled", + "unicode": "e663", + "unicode_decimal": 58979 + }, + { + "icon_id": "24855896", + "name": "gear", + "font_class": "gear", + "unicode": "e664", + "unicode_decimal": 58980 + }, + { + "icon_id": "24855897", + "name": "smallcircle-filled", + "font_class": "smallcircle-filled", + "unicode": "e665", + "unicode_decimal": 58981 + }, + { + "icon_id": "24855898", + "name": "map-filled", + "font_class": "map-filled", + "unicode": "e666", + "unicode_decimal": 58982 + }, + { + "icon_id": "24855899", + "name": "map", + "font_class": "map", + "unicode": "e667", + "unicode_decimal": 58983 + }, + { + "icon_id": "24855825", + "name": "refresh-filled", + "font_class": "refresh-filled", + "unicode": "e656", + "unicode_decimal": 58966 + }, + { + "icon_id": "24855826", + "name": "refresh", + "font_class": "refresh", + "unicode": "e657", + "unicode_decimal": 58967 + }, + { + "icon_id": "24855808", + "name": "cloud-upload", + "font_class": "cloud-upload", + "unicode": "e645", + "unicode_decimal": 58949 + }, + { + "icon_id": "24855809", + "name": "cloud-download-filled", + "font_class": "cloud-download-filled", + "unicode": "e646", + "unicode_decimal": 58950 + }, + { + "icon_id": "24855810", + "name": "cloud-download", + "font_class": "cloud-download", + "unicode": "e647", + "unicode_decimal": 58951 + }, + { + "icon_id": "24855811", + "name": "cloud-upload-filled", + "font_class": "cloud-upload-filled", + "unicode": "e648", + "unicode_decimal": 58952 + }, + { + "icon_id": "24855813", + "name": "redo", + "font_class": "redo", + "unicode": "e64a", + "unicode_decimal": 58954 + }, + { + "icon_id": "24855814", + "name": "images-filled", + "font_class": "images-filled", + "unicode": "e64b", + "unicode_decimal": 58955 + }, + { + "icon_id": "24855815", + "name": "undo-filled", + "font_class": "undo-filled", + "unicode": "e64c", + "unicode_decimal": 58956 + }, + { + "icon_id": "24855816", + "name": "more", + "font_class": "more", + "unicode": "e64d", + "unicode_decimal": 58957 + }, + { + "icon_id": "24855817", + "name": "more-filled", + "font_class": "more-filled", + "unicode": "e64e", + "unicode_decimal": 58958 + }, + { + "icon_id": "24855818", + "name": "undo", + "font_class": "undo", + "unicode": "e64f", + "unicode_decimal": 58959 + }, + { + "icon_id": "24855819", + "name": "images", + "font_class": "images", + "unicode": "e650", + "unicode_decimal": 58960 + }, + { + "icon_id": "24855821", + "name": "paperclip", + "font_class": "paperclip", + "unicode": "e652", + "unicode_decimal": 58962 + }, + { + "icon_id": "24855822", + "name": "settings", + "font_class": "settings", + "unicode": "e653", + "unicode_decimal": 58963 + }, + { + "icon_id": "24855823", + "name": "search", + "font_class": "search", + "unicode": "e654", + "unicode_decimal": 58964 + }, + { + "icon_id": "24855824", + "name": "redo-filled", + "font_class": "redo-filled", + "unicode": "e655", + "unicode_decimal": 58965 + }, + { + "icon_id": "24841702", + "name": "list", + "font_class": "list", + "unicode": "e644", + "unicode_decimal": 58948 + }, + { + "icon_id": "24841489", + "name": "mail-open-filled", + "font_class": "mail-open-filled", + "unicode": "e63a", + "unicode_decimal": 58938 + }, + { + "icon_id": "24841491", + "name": "hand-thumbsdown-filled", + "font_class": "hand-down-filled", + "unicode": "e63c", + "unicode_decimal": 58940 + }, + { + "icon_id": "24841492", + "name": "hand-thumbsdown", + "font_class": "hand-down", + "unicode": "e63d", + "unicode_decimal": 58941 + }, + { + "icon_id": "24841493", + "name": "hand-thumbsup-filled", + "font_class": "hand-up-filled", + "unicode": "e63e", + "unicode_decimal": 58942 + }, + { + "icon_id": "24841494", + "name": "hand-thumbsup", + "font_class": "hand-up", + "unicode": "e63f", + "unicode_decimal": 58943 + }, + { + "icon_id": "24841496", + "name": "heart-filled", + "font_class": "heart-filled", + "unicode": "e641", + "unicode_decimal": 58945 + }, + { + "icon_id": "24841498", + "name": "mail-open", + "font_class": "mail-open", + "unicode": "e643", + "unicode_decimal": 58947 + }, + { + "icon_id": "24841488", + "name": "heart", + "font_class": "heart", + "unicode": "e639", + "unicode_decimal": 58937 + }, + { + "icon_id": "24839963", + "name": "loop", + "font_class": "loop", + "unicode": "e633", + "unicode_decimal": 58931 + }, + { + "icon_id": "24839866", + "name": "pulldown", + "font_class": "pulldown", + "unicode": "e632", + "unicode_decimal": 58930 + }, + { + "icon_id": "24813798", + "name": "scan", + "font_class": "scan", + "unicode": "e62a", + "unicode_decimal": 58922 + }, + { + "icon_id": "24813786", + "name": "bars", + "font_class": "bars", + "unicode": "e627", + "unicode_decimal": 58919 + }, + { + "icon_id": "24813788", + "name": "cart-filled", + "font_class": "cart-filled", + "unicode": "e629", + "unicode_decimal": 58921 + }, + { + "icon_id": "24813790", + "name": "checkbox", + "font_class": "checkbox", + "unicode": "e62b", + "unicode_decimal": 58923 + }, + { + "icon_id": "24813791", + "name": "checkbox-filled", + "font_class": "checkbox-filled", + "unicode": "e62c", + "unicode_decimal": 58924 + }, + { + "icon_id": "24813794", + "name": "shop", + "font_class": "shop", + "unicode": "e62f", + "unicode_decimal": 58927 + }, + { + "icon_id": "24813795", + "name": "headphones", + "font_class": "headphones", + "unicode": "e630", + "unicode_decimal": 58928 + }, + { + "icon_id": "24813796", + "name": "cart", + "font_class": "cart", + "unicode": "e631", + "unicode_decimal": 58929 + } + ] +} diff --git a/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 00000000..86e74445 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/yanzhu-ui-app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..835f33bc9411461b8b9046b3fec742e921d6ce3a GIT binary patch literal 35760 zcmeFacbp?vl{Q?rN>WLsSXIigCAC7gI!S6tox^m`be^1}CwPJ>yxZ{uSzi{WC_=LI+*Wx!<-H!v})21fuKMZQ#fB2Fs zuEGwU_ZyDmuR3&e_s&PS@Be}0T=(JF$l;w=9Als0-iQ4lE^0cm^YDeWhnK#G<4!$@ z>-QZydhsP6Kl0Pv9Cw|EbP-?YO$@C;`+ zuKnR1zxV)MXnddfv56Dn_-W<%#_jZ^d%1f!hyI(6O8C!lXY}93nl=3f9^gzbYS03Jm0vJ;T)Z1IKntfUtypB#zx`e6wG3 zC5AhB&Me^QdH${3yL1otSUp#NN^cKN_yKnkm%XqxczWUgrT^Oo|6lL`SPy&+DZ_DX z1{?B^82rf|!cpSXHhg1*;kZecHy+MI*MqCu>g9T0eYieaf9edzAC9!tJL|pm0UQ~l zBQN;JaG!_sb8)VT%i=%By_I_#_ZIFh?(N(=xVtf?-^|^~y@`7RcMEqbcN=#*_eSmx z?)BVjxU0EqFm9T;Q`~9pTJAdTdhWH{>+qBtxEr~fxSP3Gb60T(xkKDx?g)33JH{R7 zPH-1465x0fg%5CGeb33>TxSiZCZa24wyO7(&Q z>$wfwMs5?gnVaOMxM^;NYvpFSIc_<(f-7(s&u0CxL#u8VbF$klItIryQ@x|5W z48lm`>dOtnnB(dz48rK+>MISxIOOW948n-y>Z=XH*yQSK48kbo>T3axcUVKK~8Y>od!W-aP?gVL3VKU-3CF5aP>U~L7s5+3k`x~;p%%0f{fwn z`wW7#;p+Phg52Ti2MmG);_4R}1X;w@scs-hC9Y0&13^AJNK#+l4o$3aH zH00`3HxT3^SEssxAR)Or)eQt$$+z7tkWDxWPSHIIBXb!IaW`m$ZxcXZRf;QpmZ#4*d zg{!~KAZQq_ewRVeHC+Ae20`m^^>-Kq{lnGoHVB%CtKVY~bP`v;*C1#ou700E&{JIf zeuJQ~xcWN{g6`t#?=lEljH|!fAm}r${tpI0vvKtY41$j1>hCcK+K#I~Xb|)sSAVZT z(12Y1eFi}na`pEc1g*%`|Ir}mN3Q+>gPp}tAE%avLosrF^GJG z`bQ0dZsqD9GYDFitAE@e=v%J-34@?{x%wv!f)3{DpE3yAn5#cz5cD!v|Fl8S&|Lj9 z20>SI_0JjvtVjlpxwFpV+N5QQ~$g{(D+>a3kE^= zbM-G81S^26f5{-&16=*f2Ej7m>R&MkHUd}wszKz<)E_qpb^}-cnn7g6)t@j3wggxI zxp1QBm2=klxXa|a&TVx+;Qp=WwVt{>D}O~9QXW)O>O0h5db_-@^8Ud$^pPT-1=NS-v_4k2r|_kM*0!vaW9xyNll~`AaKH zuPQxR4wv6t{%QC2?wh**v$DGKU?rS_5?F|crGafkiL7dNk-%Y_E4VmkSn6>Hb;SUukEx3l0# zej=BS$yT%Av8Uc*J`xpdRw>aQ5n{34Scli{%@0hjo|#!%t;CXMOO1~vM@By$$wu(0 z7+*JsbCF0c%-{dHFL+pQI~s3&zjaOf89{d%!`6o3fsCO(`6

PqiNa$~E4XJ#a8s%?nsx`&SiQ7Wz{CE9c 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 literal 0 HcmV?d00001 diff --git a/yanzhu-ui-app/uni_modules/uni-icons/package.json b/yanzhu-ui-app/uni_modules/uni-icons/package.json new file mode 100644 index 00000000..d1c4e77d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-icons/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-icons", + "displayName": "uni-icons 图标", + "version": "1.3.5", + "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。", + "keywords": [ + "uni-ui", + "uniui", + "icon", + "图标" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.2.14" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-icons/readme.md b/yanzhu-ui-app/uni_modules/uni-icons/readme.md new file mode 100644 index 00000000..86234ba1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-icons/readme.md @@ -0,0 +1,8 @@ +## Icons 图标 +> **组件名:uni-icons** +> 代码块: `uIcons` + +用于展示 icons 图标 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/yanzhu-ui-app/uni_modules/uni-indexed-list/changelog.md b/yanzhu-ui-app/uni_modules/uni-indexed-list/changelog.md new file mode 100644 index 00000000..08fa71cb --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-indexed-list/changelog.md @@ -0,0 +1,17 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-indexed-list](https://uniapp.dcloud.io/component/uniui/uni-indexed-list) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.11(2021-05-12) +- 新增 组件示例地址 +## 1.0.10(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.8(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 diff --git a/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue b/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue new file mode 100644 index 00000000..2f13baec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue b/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue new file mode 100644 index 00000000..35e168c2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue @@ -0,0 +1,367 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-indexed-list/package.json b/yanzhu-ui-app/uni_modules/uni-indexed-list/package.json new file mode 100644 index 00000000..125c0e7f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-indexed-list/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-indexed-list", + "displayName": "uni-indexed-list 索引列表", + "version": "1.2.1", + "description": "索引列表组件,右侧带索引的列表,方便快速定位到具体内容,通常用于城市/机场选择等场景", + "keywords": [ + "uni-ui", + "索引列表", + "索引", + "列表" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-indexed-list/readme.md b/yanzhu-ui-app/uni_modules/uni-indexed-list/readme.md new file mode 100644 index 00000000..44ad84b2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-indexed-list/readme.md @@ -0,0 +1,11 @@ + + +## IndexedList 索引列表 +> **组件名:uni-indexed-list** +> 代码块: `uIndexedList` + + +用于展示索引列表。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-indexed-list) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/yanzhu-ui-app/uni_modules/uni-link/changelog.md b/yanzhu-ui-app/uni_modules/uni-link/changelog.md new file mode 100644 index 00000000..2cfbf591 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-link/changelog.md @@ -0,0 +1,17 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-link](https://uniapp.dcloud.io/component/uniui/uni-link) +## 1.1.7(2021-11-08) +## 0.0.7(2021-09-03) +- 修复 在 nvue 下不显示的 bug +## 0.0.6(2021-07-30) +- 新增 支持自定义插槽 +## 0.0.5(2021-06-21) +- 新增 download 属性,H5平台下载文件名 +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-03-09) +- 新增 href 属性支持 tel:|mailto: + +## 0.0.2(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-link/components/uni-link/uni-link.vue b/yanzhu-ui-app/uni_modules/uni-link/components/uni-link/uni-link.vue new file mode 100644 index 00000000..27c5468e --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-link/components/uni-link/uni-link.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-link/package.json b/yanzhu-ui-app/uni_modules/uni-link/package.json new file mode 100644 index 00000000..77b19865 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-link/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-link", + "displayName": "uni-link 超链接", + "version": "1.0.0", + "description": "uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打", + "keywords": [ + "uni-ui", + "uniui", + "link", + "超链接", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-link/readme.md b/yanzhu-ui-app/uni_modules/uni-link/readme.md new file mode 100644 index 00000000..7f09e941 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-link/readme.md @@ -0,0 +1,11 @@ + + +## Link 链接 +> **组件名:uni-link** +> 代码块: `uLink` + + +uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打开新网页。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-link) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-list/changelog.md b/yanzhu-ui-app/uni_modules/uni-list/changelog.md new file mode 100644 index 00000000..8254a185 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/changelog.md @@ -0,0 +1,46 @@ +## 1.2.14(2023-04-14) +- 优化 uni-list-chat 具名插槽`header` 非app端套一层元素,方便使用时通过外层元素定位实现样式修改 +## 1.2.13(2023-03-03) +- uni-list-chat 新增 支持具名插槽`header` +## 1.2.12(2023-02-01) +- 新增 列表图标新增 customPrefix 属性 ,用法 [详见](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props) +## 1.2.11(2023-01-31) +- 修复 无反馈效果呈现的bug +## 1.2.9(2022-11-22) +- 修复 uni-list-chat 在vue3下跳转报错的bug +## 1.2.8(2022-11-21) +- 修复 uni-list-chat avatar属性 值为本地路径时错误的问题 +## 1.2.7(2022-11-21) +- 修复 uni-list-chat avatar属性 在腾讯云版uniCloud下错误的问题 +## 1.2.6(2022-11-18) +- 修复 uni-list-chat note属性 支持:“草稿”字样功能 文本少1位的问题 +## 1.2.5(2022-11-15) +- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug +## 1.2.4(2022-11-15) +- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug +## 1.2.3(2022-11-14) +- uni-list-chat 新增 avatar 支持 fileId +## 1.2.2(2022-11-11) +- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html) +- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im) +- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor +## 1.2.1(2022-03-30) +- 删除无用文件 +## 1.2.0(2021-11-23) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list) +## 1.1.3(2021-08-30) +- 修复 在vue3中to属性在发行应用的时候报错的bug +## 1.1.2(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.1(2021-07-21) +- 修复 与其他组件嵌套使用时,点击失效的Bug +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.17(2021-05-12) +- 新增 组件示例地址 +## 1.0.16(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.15(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 uni-list-chat 角标显示不正常的问题 diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue new file mode 100644 index 00000000..097cdab8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss new file mode 100644 index 00000000..311f8d9f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss @@ -0,0 +1,58 @@ +/** + * 这里是 uni-list 组件内置的常用样式变量 + * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码 + * + */ + +// 背景色 +$background-color : #fff; +// 分割线颜色 +$divide-line-color : #e5e5e5; + +// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像 +// nvue 页面不支持修改头像大小 +$avatar-width : 45px ; + +// 头像边框 +$avatar-border-radius: 5px; +$avatar-border-color: #eee; +$avatar-border-width: 1px; + +// 标题文字样式 +$title-size : 16px; +$title-color : #3b4144; +$title-weight : normal; + +// 描述文字样式 +$note-size : 12px; +$note-color : #999; +$note-weight : normal; + +// 右侧额外内容默认样式 +$right-text-size : 12px; +$right-text-color : #999; +$right-text-weight : normal; + +// 角标样式 +// nvue 页面不支持修改圆点位置以及大小 +// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动 +$badge-left: 0px; +$badge-top: 0px; + +// 显示圆点时,圆点大小 +$dot-width: 10px; +$dot-height: 10px; + +// 显示角标时,角标大小和字体大小 +$badge-size : 18px; +$badge-font : 12px; +// 显示角标时,角标前景色 +$badge-color : #fff; +// 显示角标时,角标背景色 +$badge-background-color : #ff5a5f; +// 显示角标时,角标左右间距 +$badge-space : 6px; + +// 状态样式 +// 选中颜色 +$hover : #f5f5f5; diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue new file mode 100644 index 00000000..4692b808 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue @@ -0,0 +1,593 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue new file mode 100644 index 00000000..a274ac8f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue @@ -0,0 +1,534 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-list.vue b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-list.vue new file mode 100644 index 00000000..6ef5972a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-list.vue @@ -0,0 +1,123 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.vue b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.vue new file mode 100644 index 00000000..3b4c5a23 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs new file mode 100644 index 00000000..ac98f4dd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs @@ -0,0 +1,87 @@ +var pullDown = { + threshold: 95, + maxHeight: 200, + callRefresh: 'onrefresh', + callPullingDown: 'onpullingdown', + refreshSelector: '.uni-refresh' +}; + +function ready(newValue, oldValue, ownerInstance, instance) { + var state = instance.getState() + state.canPullDown = newValue; + // //console.log(newValue); +} + +function touchStart(e, instance) { + var state = instance.getState(); + state.refreshInstance = instance.selectComponent(pullDown.refreshSelector); + state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined); + if (!state.canPullDown) { + return + } + + // //console.log("touchStart"); + + state.height = 0; + state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY; + state.refreshInstance.setStyle({ + 'height': 0 + }); + state.refreshInstance.callMethod("onchange", true); +} + +function touchMove(e, ownerInstance) { + var instance = e.instance; + var state = instance.getState(); + if (!state.canPullDown) { + return + } + + var oldHeight = state.height; + var endY = e.touches[0].pageY || e.changedTouches[0].pageY; + var height = endY - state.touchStartY; + if (height > pullDown.maxHeight) { + return; + } + + var refreshInstance = state.refreshInstance; + refreshInstance.setStyle({ + 'height': height + 'px' + }); + + height = height < pullDown.maxHeight ? height : pullDown.maxHeight; + state.height = height; + refreshInstance.callMethod(pullDown.callPullingDown, { + height: height + }); +} + +function touchEnd(e, ownerInstance) { + var state = e.instance.getState(); + if (!state.canPullDown) { + return + } + + state.refreshInstance.callMethod("onchange", false); + + var refreshInstance = state.refreshInstance; + if (state.height > pullDown.threshold) { + refreshInstance.callMethod(pullDown.callRefresh); + return; + } + + refreshInstance.setStyle({ + 'height': 0 + }); +} + +function propObserver(newValue, oldValue, instance) { + pullDown = newValue; +} + +module.exports = { + touchmove: touchMove, + touchstart: touchStart, + touchend: touchEnd, + propObserver: propObserver +} diff --git a/yanzhu-ui-app/uni_modules/uni-list/package.json b/yanzhu-ui-app/uni_modules/uni-list/package.json new file mode 100644 index 00000000..8350efce --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-list", + "displayName": "uni-list 列表", + "version": "1.2.14", + "description": "List 组件 ,帮助使用者快速构建列表。", + "keywords": [ + "", + "uni-ui", + "uniui", + "列表", + "", + "list" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-badge", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-list/readme.md b/yanzhu-ui-app/uni_modules/uni-list/readme.md new file mode 100644 index 00000000..32c28654 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-list/readme.md @@ -0,0 +1,346 @@ +## List 列表 +> **组件名:uni-list** +> 代码块: `uList`、`uListItem` +> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad` + + +List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。 + +在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。 + +uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。 + +uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。 + +内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。 + +涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。 + +下文均有样例给出。 + +uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29) + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 组件需要依赖 `sass` 插件 ,请自行手动安装 +> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件 +> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item` +> - 只有开启点击反馈后,会有点击选中效果 +> - 使用插槽时,可以完全自定义内容 +> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展 +> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译 +> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义 +> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli` +> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + +### 基本用法 + +- 设置 `title` 属性,可以显示列表标题 +- 设置 `disabled` 属性,可以禁用当前项 + +```html + + + + + +``` + +### 多行内容显示 + +- 设置 `note` 属性 ,可以在第二行显示描述文本信息 + +```html + + + + + +``` + +### 右侧显示角标、switch + +- 设置 `show-badge` 属性 ,可以显示角标内容 +- 设置 `show-switch` 属性,可以显示 switch 开关 + +```html + + + + + +``` + +### 左侧显示略缩图、图标 + +- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图 +- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标 + +```html + + + + +``` + +### 开启点击反馈和右侧箭头 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头 +- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` + +```html + + + + + + + +``` + + +### 聊天列表示例 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` +- 设置 `to` 属性,可以跳转页面 +- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示 +- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效 +- 可以通过默认插槽自定义列表右侧内容 + +```html + + + + + + + + + + + + + + + + + 刚刚 + + + + + + + +``` + +```javascript + +export default { + components: {}, + data() { + return { + avatarList: [{ + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }] + } + } +} + +``` + + +```css + +.chat-custom-right { + flex: 1; + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; + justify-content: space-between; + align-items: flex-end; +} + +.chat-custom-text { + font-size: 12px; + color: #999; +} + +``` + +## API + +### List Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +border |Boolean |true | 是否显示边框 + + +### ListItem Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +ellipsis |Number |0 | title 是否溢出隐藏,可选值,0:默认; 1:显示一行; 2:显示两行;【nvue 暂不支持】 +thumb |String |- | 左侧缩略图,若thumb有值,则不会显示扩展图标 +thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium:一般; sm:小图; +showBadge |Boolean |false | 是否显示数字角标 +badgeText |String |- | 数字角标内容 +badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) +badgeStyle |Object |- | 数字角标样式,使用uni-badge的custom-style参数 +rightText |String |- | 右侧文字内容 +disabled |Boolean |false | 是否禁用 +showArrow |Boolean |true | 是否显示箭头图标 +link |String |navigateTo | 新页面跳转方式,可选值见下表 +to |String |- | 新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功 +clickable |Boolean |false | 是否开启点击反馈 +showSwitch |Boolean |false | 是否显示Switch +switchChecked |Boolean |false | Switch是否被选中 +showExtraIcon |Boolean |false | 左侧是否显示扩展图标 +extraIcon |Object |- | 扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28) +direction | String |row | 排版方向,可选值,row:水平排列; column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制 + + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItem Events + +事件称名 |说明 |返回参数 +:-: |:-: |:-: +click |点击 uniListItem 触发事件,需开启点击反馈 |- +switchChange |点击切换 Switch 时触发,需显示 switch |e={value:checked} + + + +### ListItem Slots + +名称 | 说明 +:-: | :-: +header | 左/上内容插槽,可完全自定义默认显示 +body | 中间内容插槽,可完全自定义中间内容 +footer | 右/下内容插槽,可完全自定义右侧内容 + + +> **通过插槽扩展** +> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现 +> 如果 `uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。 +> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer` +> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分 +> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分 +> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。 + + +**示例** + +```html + + + + + + + + + 自定义插槽 + + + + +``` + + + + + +### ListItemChat Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +clickable |Boolean |false | 是否开启点击反馈 +badgeText |String |- | 数字角标内容,设置为 `dot` 将显示圆点 +badgePositon |String |right | 角标位置 +link |String |navigateTo | 是否展示右侧箭头并开启点击反馈,可选值见下表 +clickable |Boolean |false | 是否开启点击反馈 +to |String |- | 跳转页面地址,如填写此属性,click 会返回页面是否跳转成功 +time |String |- | 右侧时间显示 +avatarCircle |Boolean |false | 是否显示圆形头像 +avatar |String |- | 头像地址,avatarCircle 不填时生效 +avatarList |Array |- | 头像组,格式为 [{url:''}] + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItemChat Slots + +名称 | 说明 +:- | :- +default | 自定义列表右侧内容(包括时间和角标显示) + +### ListItemChat Events +事件称名 | 说明 | 返回参数 +:-: | :-: | :-: +@click | 点击 uniListChat 触发事件 | {data:{}} ,如有 to 属性,会返回页面跳转信息 + + + + + + +## 基于uni-list扩展的页面模板 + +通过扩展插槽,可实现多种常见样式的列表 + +**新闻列表类** + +1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546) +2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583) +3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584) +4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585) +5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586) +6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587) +7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588) + +**商品列表类** + +1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651) +2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671) +3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672) + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list) \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/changelog.md b/yanzhu-ui-app/uni_modules/uni-load-more/changelog.md new file mode 100644 index 00000000..8f03f1d5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/changelog.md @@ -0,0 +1,19 @@ +## 1.3.3(2022-01-20) +- 新增 showText属性 ,是否显示文本 +## 1.3.2(2022-01-19) +- 修复 nvue 平台下不显示文本的bug +## 1.3.1(2022-01-19) +- 修复 微信小程序平台样式选择器报警告的问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more) +## 1.2.1(2021-08-24) +- 新增 支持国际化 +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.8(2021-05-12) +- 新增 组件示例地址 +## 1.1.7(2021-03-30) +- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug +## 1.1.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json new file mode 100644 index 00000000..a4f14a54 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "Pull up to show more", + "uni-load-more.contentrefresh": "loading...", + "uni-load-more.contentnomore": "No more data" +} diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json new file mode 100644 index 00000000..f15d5105 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉显示更多", + "uni-load-more.contentrefresh": "正在加载...", + "uni-load-more.contentnomore": "没有更多数据了" +} diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json new file mode 100644 index 00000000..a255c6de --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉顯示更多", + "uni-load-more.contentrefresh": "正在加載...", + "uni-load-more.contentnomore": "沒有更多數據了" +} diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue new file mode 100644 index 00000000..e5eff4d6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue @@ -0,0 +1,399 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/package.json b/yanzhu-ui-app/uni_modules/uni-load-more/package.json new file mode 100644 index 00000000..2fa6f040 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-load-more", + "displayName": "uni-load-more 加载更多", + "version": "1.3.3", + "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。", + "keywords": [ + "uni-ui", + "uniui", + "加载更多", + "load-more" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-load-more/readme.md b/yanzhu-ui-app/uni_modules/uni-load-more/readme.md new file mode 100644 index 00000000..54dc1fad --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-load-more/readme.md @@ -0,0 +1,14 @@ + + +### LoadMore 加载更多 +> **组件名:uni-load-more** +> 代码块: `uLoadMore` + + +用于列表中,做滚动加载使用,展示 loading 的各种状态。 + + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-nav-bar/changelog.md b/yanzhu-ui-app/uni_modules/uni-nav-bar/changelog.md new file mode 100644 index 00000000..0f9a2f1b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-nav-bar/changelog.md @@ -0,0 +1,51 @@ +## 1.3.11(2023-03-29) +- 修复 自定义状态栏高度闪动BUG +## 1.3.10(2023-03-29) +- 修复 暗黑模式下边线颜色错误的bug +## 1.3.9(2022-10-13) +- 修复 条件编译错误的bug +## 1.3.8(2022-10-12) +- 修复 nvue 环境 fixed 为 true 的情况下,无法置顶的 bug +## 1.3.7(2022-08-11) +- 修复 nvue 环境下 fixed 为 true 的情况下,无法置顶的 bug +## 1.3.6(2022-06-30) +- 修复 组件示例中插槽用法无法显示内容的bug +## 1.3.5(2022-05-24) +- 新增 stat 属性 ,可开启统计title 上报 ,仅使用了title 属性且项目开启了uni统计生效 +## 1.3.4(2022-01-24) +- 更新 组件示例 +## 1.3.3(2022-01-24) +- 新增 left-width/right-width属性 ,可修改左右两侧的宽度 +## 1.3.2(2022-01-18) +- 修复 在vue下,标题不垂直居中的bug +## 1.3.1(2022-01-18) +- 修复 height 属性类型错误 +## 1.3.0(2022-01-18) +- 新增 height 属性,可修改组件高度 +- 新增 dark 属性可可开启暗黑模式 +- 优化 标题字数过多显示省略号 +- 优化 插槽,插入内容可完全覆盖 +## 1.2.1(2022-01-10) +- 修复 color 属性不生效的bug +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-nav-bar](https://uniapp.dcloud.io/component/uniui/uni-nav-bar) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.11(2021-05-12) +- 新增 组件示例地址 +## 1.0.10(2021-04-30) +- 修复 在nvue下fixed为true,宽度不能撑满的Bug +## 1.0.9(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.8(2021-04-14) +- uni-ui 修复 uni-nav-bar 当 fixed 属性为 true 时铺不满屏幕的 bug + +## 1.0.7(2021-02-25) +- 修复 easycom 下,找不到 uni-status-bar 的bug + +## 1.0.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue new file mode 100644 index 00000000..c8908606 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue @@ -0,0 +1,357 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue b/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue new file mode 100644 index 00000000..4ac73aec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-nav-bar/package.json b/yanzhu-ui-app/uni_modules/uni-nav-bar/package.json new file mode 100644 index 00000000..240ae959 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-nav-bar/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-nav-bar", + "displayName": "uni-nav-bar 自定义导航栏", + "version": "1.3.11", + "description": "自定义导航栏组件,主要用于头部导航。", + "keywords": [ + "uni-ui", + "导航", + "导航栏", + "自定义导航栏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-nav-bar/readme.md b/yanzhu-ui-app/uni_modules/uni-nav-bar/readme.md new file mode 100644 index 00000000..3934b327 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-nav-bar/readme.md @@ -0,0 +1,15 @@ + + +## NavBar 导航栏 +> **组件名:uni-nav-bar** +> 代码块: `uNavBar` + +导航栏组件,主要用于头部导航。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-nav-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-notice-bar/changelog.md b/yanzhu-ui-app/uni_modules/uni-notice-bar/changelog.md new file mode 100644 index 00000000..d5268115 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-notice-bar/changelog.md @@ -0,0 +1,18 @@ +## 1.2.1(2022-09-05) +- 新增 属性 fontSize,可修改文字大小。 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-notice-bar](https://uniapp.dcloud.io/component/uniui/uni-notice-bar) +## 1.1.1(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.9(2021-05-12) +- 新增 组件示例地址 +## 1.0.8(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.7(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue b/yanzhu-ui-app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue new file mode 100644 index 00000000..98d4720c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue @@ -0,0 +1,426 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-notice-bar/package.json b/yanzhu-ui-app/uni_modules/uni-notice-bar/package.json new file mode 100644 index 00000000..8d9b13cd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-notice-bar/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-notice-bar", + "displayName": "uni-notice-bar 通告栏", + "version": "1.2.1", + "description": "NoticeBar 通告栏组件,常用于展示公告信息,可设为滚动公告", + "keywords": [ + "uni-ui", + "uniui", + "通告栏", + "公告", + "跑马灯" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-notice-bar/readme.md b/yanzhu-ui-app/uni_modules/uni-notice-bar/readme.md new file mode 100644 index 00000000..fb2ede24 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-notice-bar/readme.md @@ -0,0 +1,13 @@ + + +## NoticeBar 通告栏 +> **组件名:uni-notice-bar** +> 代码块: `uNoticeBar` + + +通告栏组件 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-notice-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-number-box/changelog.md b/yanzhu-ui-app/uni_modules/uni-number-box/changelog.md new file mode 100644 index 00000000..5925c32a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-number-box/changelog.md @@ -0,0 +1,25 @@ +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-number-box](https://uniapp.dcloud.io/component/uniui/uni-number-box) +## 1.1.2(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.1.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-20) +- 修复 uni-number-box 浮点数运算不精确的 bug +- 修复 uni-number-box change 事件触发不正确的 bug +- 新增 uni-number-box v-model 双向绑定 +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 + +## 1.0.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 v-model +- 新增 支持 focus、blur 事件 +- 新增 支持 PC 端 diff --git a/yanzhu-ui-app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue b/yanzhu-ui-app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue new file mode 100644 index 00000000..e91c0321 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue @@ -0,0 +1,221 @@ + + + diff --git a/yanzhu-ui-app/uni_modules/uni-number-box/package.json b/yanzhu-ui-app/uni_modules/uni-number-box/package.json new file mode 100644 index 00000000..ad823368 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-number-box/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-number-box", + "displayName": "uni-number-box 数字输入框", + "version": "1.2.1", + "description": "NumberBox 带加减按钮的数字输入框组件,用户可以控制每次点击增加的数值,支持小数。", + "keywords": [ + "uni-ui", + "uniui", + "数字输入框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-number-box/readme.md b/yanzhu-ui-app/uni_modules/uni-number-box/readme.md new file mode 100644 index 00000000..affc56fa --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-number-box/readme.md @@ -0,0 +1,13 @@ + + +## NumberBox 数字输入框 +> **组件名:uni-number-box** +> 代码块: `uNumberBox` + + +带加减按钮的数字输入框。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-number-box) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/changelog.md b/yanzhu-ui-app/uni_modules/uni-pagination/changelog.md new file mode 100644 index 00000000..2e94adc4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/changelog.md @@ -0,0 +1,27 @@ +## 1.2.4(2022-09-19) +- 修复,未对主题色设置默认色,导致未引入 uni-scss 变量文件报错。 +- 修复,未对移动端当前页文字做主题色适配。 +## 1.2.3(2022-09-15) +- 修复未使用 uni-scss 主题色的 bug。 +## 1.2.2(2022-07-06) +- 修复 es 语言 i18n 错误 +## 1.2.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination) +## 1.1.2(2021-10-08) +- 修复 current 、value 属性未监听,导致高亮样式失效的 bug +## 1.1.1(2021-08-20) +- 新增 支持国际化 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-05-12) +- 新增 组件示例地址 +## 1.0.6(2021-04-12) +- 新增 PC 和 移动端适配不同的 ui +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json new file mode 100644 index 00000000..d6e28977 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json @@ -0,0 +1,5 @@ +{ + "uni-pagination.prevText": "prev", + "uni-pagination.nextText": "next", + "uni-pagination.piecePerPage": "piece/page" +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json new file mode 100644 index 00000000..604a1138 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json @@ -0,0 +1,5 @@ +{ + "uni-pagination.prevText": "anterior", + "uni-pagination.nextText": "prxima", + "uni-pagination.piecePerPage": "Artculo/Pgina" +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json new file mode 100644 index 00000000..a7a0c774 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json @@ -0,0 +1,5 @@ +{ + "uni-pagination.prevText": "précédente", + "uni-pagination.nextText": "suivante", + "uni-pagination.piecePerPage": "Articles/Pages" +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js new file mode 100644 index 00000000..2469dd02 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js @@ -0,0 +1,12 @@ +import en from './en.json' +import es from './es.json' +import fr from './fr.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + es, + fr, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json new file mode 100644 index 00000000..782bbe4a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json @@ -0,0 +1,5 @@ +{ + "uni-pagination.prevText": "上一页", + "uni-pagination.nextText": "下一页", + "uni-pagination.piecePerPage": "条/页" +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json new file mode 100644 index 00000000..180fddbd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json @@ -0,0 +1,5 @@ +{ + "uni-pagination.prevText": "上一頁", + "uni-pagination.nextText": "下一頁", + "uni-pagination.piecePerPage": "條/頁" +} diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue new file mode 100644 index 00000000..5305b5f1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue @@ -0,0 +1,465 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/package.json b/yanzhu-ui-app/uni_modules/uni-pagination/package.json new file mode 100644 index 00000000..862d5abd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-pagination", + "displayName": "uni-pagination 分页器", + "version": "1.2.4", + "description": "Pagination 分页器组件,用于展示页码、请求数据等。", + "keywords": [ + "uni-ui", + "uniui", + "分页器", + "页码" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-pagination/readme.md b/yanzhu-ui-app/uni_modules/uni-pagination/readme.md new file mode 100644 index 00000000..97ea1d63 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-pagination/readme.md @@ -0,0 +1,11 @@ + + +## Pagination 分页器 +> **组件名:uni-pagination** +> 代码块: `uPagination` + + +分页器组件,用于展示页码、请求数据等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-pagination) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/yanzhu-ui-app/uni_modules/uni-popup/changelog.md b/yanzhu-ui-app/uni_modules/uni-popup/changelog.md new file mode 100644 index 00000000..bc59f072 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/changelog.md @@ -0,0 +1,68 @@ +## 1.8.3(2023-04-17) +- 修复 uni-popup 重复打开时的 bug +## 1.8.2(2023-02-02) +- uni-popup-dialog 组件新增 inputType 属性 +## 1.8.1(2022-12-01) +- 修复 nvue 下 v-show 报错 +## 1.8.0(2022-11-29) +- 优化 主题样式 +## 1.7.9(2022-04-02) +- 修复 弹出层内部无法滚动的bug +## 1.7.8(2022-03-28) +- 修复 小程序中高度错误的bug +## 1.7.7(2022-03-17) +- 修复 快速调用open出现问题的Bug +## 1.7.6(2022-02-14) +- 修复 safeArea 属性不能设置为false的bug +## 1.7.5(2022-01-19) +- 修复 isMaskClick 失效的bug +## 1.7.4(2022-01-19) +- 新增 cancelText \ confirmText 属性 ,可自定义文本 +- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 +- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 +## 1.7.3(2022-01-13) +- 修复 设置 safeArea 属性不生效的bug +## 1.7.2(2021-11-26) +- 优化 组件示例 +## 1.7.1(2021-11-26) +- 修复 vuedoc 文字错误 +## 1.7.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup) +## 1.6.2(2021-08-24) +- 新增 支持国际化 +## 1.6.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.6.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.5.0(2021-06-23) +- 新增 mask-click 遮罩层点击事件 +## 1.4.5(2021-06-22) +- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.4(2021-06-18) +- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.3(2021-06-08) +- 修复 错误的 watch 字段 +- 修复 safeArea 属性不生效的问题 +- 修复 点击内容,再点击遮罩无法关闭的Bug +## 1.4.2(2021-05-12) +- 新增 组件示例地址 +## 1.4.1(2021-04-29) +- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 +## 1.4.0 (2021-04-29) +- 新增 type 属性的 left\right 值,支持左右弹出 +- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 +- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 +- 新增 safeArea 属性,是否适配底部安全区 +- 修复 App\h5\微信小程序底部安全区占位不对的Bug +- 修复 App 端弹出等待的Bug +- 优化 提升低配设备性能,优化动画卡顿问题 +- 优化 更简单的组件自定义方式 +## 1.2.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.2.8(2021-02-05) +- 调整为uni_modules目录规范 +## 1.2.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 +- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js new file mode 100644 index 00000000..6ef26a26 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue new file mode 100644 index 00000000..b5eee79a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue @@ -0,0 +1,275 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue new file mode 100644 index 00000000..91370a82 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue @@ -0,0 +1,143 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue new file mode 100644 index 00000000..5be76247 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue @@ -0,0 +1,187 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/en.json new file mode 100644 index 00000000..7f1bd06a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/en.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "cancel", + "uni-popup.ok": "ok", + "uni-popup.placeholder": "pleace enter", + "uni-popup.title": "Hint", + "uni-popup.shareTitle": "Share to" +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json new file mode 100644 index 00000000..5e3003ca --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "确定", + "uni-popup.placeholder": "请输入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json new file mode 100644 index 00000000..13e39eba --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "確定", + "uni-popup.placeholder": "請輸入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/keypress.js b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/keypress.js new file mode 100644 index 00000000..62dda461 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/popup.js b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/popup.js new file mode 100644 index 00000000..c4e5781d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/popup.js @@ -0,0 +1,26 @@ + +export default { + data() { + return { + + } + }, + created(){ + this.popup = this.getParent() + }, + methods:{ + /** + * 获取父元素实例 + */ + getParent(name = 'uniPopup') { + let parent = this.$parent; + let parentName = parent.$options.name; + while (parentName !== name) { + parent = parent.$parent; + if (!parent) return false + parentName = parent.$options.name; + } + return parent; + }, + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue new file mode 100644 index 00000000..c592f300 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue @@ -0,0 +1,473 @@ + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-popup/package.json b/yanzhu-ui-app/uni_modules/uni-popup/package.json new file mode 100644 index 00000000..f40556ba --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-popup", + "displayName": "uni-popup 弹出层", + "version": "1.8.3", + "description": " Popup 组件,提供常用的弹层", + "keywords": [ + "uni-ui", + "弹出层", + "弹窗", + "popup", + "弹框" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-transition" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-popup/readme.md b/yanzhu-ui-app/uni_modules/uni-popup/readme.md new file mode 100644 index 00000000..fdad4b3d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-popup/readme.md @@ -0,0 +1,17 @@ + + +## Popup 弹出层 +> **组件名:uni-popup** +> 代码块: `uPopup` +> 关联组件:`uni-transition` + + +弹出层组件,在应用中弹出一个消息提示窗口、提示框等 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-rate/changelog.md b/yanzhu-ui-app/uni_modules/uni-rate/changelog.md new file mode 100644 index 00000000..8a98a612 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-rate/changelog.md @@ -0,0 +1,25 @@ +## 1.3.1(2022-02-25) +- 修复 条件判断 `NaN` 错误的 bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate) +## 1.2.2(2021-09-10) +- 优化 默认值修改为 0 颗星 +## 1.2.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.2.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.2(2021-05-12) +- 新增 组件示例地址 +## 1.1.1(2021-04-21) +- 修复 布局变化后 uni-rate 星星计算不准确的 bug +- 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖 +## 1.1.0(2021-04-16) +- 修复 uni-rate 属性 margin 值为 string 组件失效的 bug + +## 1.0.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.8(2021-02-05) +- 调整为uni_modules目录规范 +- 支持 pc 端 diff --git a/yanzhu-ui-app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue b/yanzhu-ui-app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue new file mode 100644 index 00000000..56616294 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue @@ -0,0 +1,365 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-rate/package.json b/yanzhu-ui-app/uni_modules/uni-rate/package.json new file mode 100644 index 00000000..64e8e332 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-rate/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-rate", + "displayName": "uni-rate 评分", + "version": "1.3.1", + "description": "Rate 评分组件,可自定义评分星星图标的大小、间隔、评分数。", + "keywords": [ + "uni-ui", + "uniui", + "评分" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-rate/readme.md b/yanzhu-ui-app/uni_modules/uni-rate/readme.md new file mode 100644 index 00000000..eae7b5ce --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-rate/readme.md @@ -0,0 +1,12 @@ + + +## Rate 评分 +> **组件名:uni-rate** +> 代码块: `uRate` +> 关联组件:`uni-icons` + + +评分组件,多用于购买商品后,对商品进行评价等场景 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-rate) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-row/changelog.md b/yanzhu-ui-app/uni_modules/uni-row/changelog.md new file mode 100644 index 00000000..5b465bc6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-row/changelog.md @@ -0,0 +1,10 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-row](https://uniapp.dcloud.io/component/uniui/uni-row) +## 0.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 新增uni-row组件 diff --git a/yanzhu-ui-app/uni_modules/uni-row/components/uni-col/uni-col.vue b/yanzhu-ui-app/uni_modules/uni-row/components/uni-col/uni-col.vue new file mode 100644 index 00000000..d5f37283 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-row/components/uni-col/uni-col.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-row/components/uni-row/uni-row.vue b/yanzhu-ui-app/uni_modules/uni-row/components/uni-row/uni-row.vue new file mode 100644 index 00000000..c7d93701 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-row/components/uni-row/uni-row.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-row/package.json b/yanzhu-ui-app/uni_modules/uni-row/package.json new file mode 100644 index 00000000..3f52fa64 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-row/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-row", + "displayName": "uni-row 布局-行", + "version": "1.0.0", + "description": "流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。", + "keywords": [ + "uni-ui", + "uniui", + "栅格", + "布局", + "layout" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "u" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-row/readme.md b/yanzhu-ui-app/uni_modules/uni-row/readme.md new file mode 100644 index 00000000..3c9c8b99 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-row/readme.md @@ -0,0 +1,10 @@ +## Layout 布局 + +> **组件名 uni-row、uni-col** +> 代码块: `uRow`、`uCol` + + +流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-row) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-scss/changelog.md b/yanzhu-ui-app/uni_modules/uni-scss/changelog.md new file mode 100644 index 00000000..b863bb0f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2022-01-21) +- 优化 组件示例 +## 1.0.2(2021-11-22) +- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 +## 1.0.1(2021-11-22) +- 修复 vue3中scss语法兼容问题 +## 1.0.0(2021-11-18) +- init diff --git a/yanzhu-ui-app/uni_modules/uni-scss/index.scss b/yanzhu-ui-app/uni_modules/uni-scss/index.scss new file mode 100644 index 00000000..1744a5f9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/index.scss @@ -0,0 +1 @@ +@import './styles/index.scss'; diff --git a/yanzhu-ui-app/uni_modules/uni-scss/package.json b/yanzhu-ui-app/uni_modules/uni-scss/package.json new file mode 100644 index 00000000..7cc0ccb7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-scss", + "displayName": "uni-scss 辅助样式", + "version": "1.0.3", + "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", + "keywords": [ + "uni-scss", + "uni-ui", + "辅助样式" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-scss/readme.md b/yanzhu-ui-app/uni_modules/uni-scss/readme.md new file mode 100644 index 00000000..b7d1c25f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/readme.md @@ -0,0 +1,4 @@ +`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/index.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/index.scss new file mode 100644 index 00000000..ffac4fec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/index.scss @@ -0,0 +1,7 @@ +@import './setting/_variables.scss'; +@import './setting/_border.scss'; +@import './setting/_color.scss'; +@import './setting/_space.scss'; +@import './setting/_radius.scss'; +@import './setting/_text.scss'; +@import './setting/_styles.scss'; diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_border.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_border.scss new file mode 100644 index 00000000..12a11c32 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_border.scss @@ -0,0 +1,3 @@ +.uni-border { + border: 1px $uni-border-1 solid; +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_color.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_color.scss new file mode 100644 index 00000000..1ededd94 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_color.scss @@ -0,0 +1,66 @@ + +// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 +// @mixin get-styles($k,$c) { +// @if $k == size or $k == weight{ +// font-#{$k}:#{$c} +// }@else{ +// #{$k}:#{$c} +// } +// } +$uni-ui-color:( + // 主色 + primary: $uni-primary, + primary-disable: $uni-primary-disable, + primary-light: $uni-primary-light, + // 辅助色 + success: $uni-success, + success-disable: $uni-success-disable, + success-light: $uni-success-light, + warning: $uni-warning, + warning-disable: $uni-warning-disable, + warning-light: $uni-warning-light, + error: $uni-error, + error-disable: $uni-error-disable, + error-light: $uni-error-light, + info: $uni-info, + info-disable: $uni-info-disable, + info-light: $uni-info-light, + // 中性色 + main-color: $uni-main-color, + base-color: $uni-base-color, + secondary-color: $uni-secondary-color, + extra-color: $uni-extra-color, + // 背景色 + bg-color: $uni-bg-color, + // 边框颜色 + border-1: $uni-border-1, + border-2: $uni-border-2, + border-3: $uni-border-3, + border-4: $uni-border-4, + // 黑色 + black:$uni-black, + // 白色 + white:$uni-white, + // 透明 + transparent:$uni-transparent +) !default; +@each $key, $child in $uni-ui-color { + .uni-#{"" + $key} { + color: $child; + } + .uni-#{"" + $key}-bg { + background-color: $child; + } +} +.uni-shadow-sm { + box-shadow: $uni-shadow-sm; +} +.uni-shadow-base { + box-shadow: $uni-shadow-base; +} +.uni-shadow-lg { + box-shadow: $uni-shadow-lg; +} +.uni-mask { + background-color:$uni-mask; +} diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_radius.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_radius.scss new file mode 100644 index 00000000..9a0428bb --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_radius.scss @@ -0,0 +1,55 @@ +@mixin radius($r,$d:null ,$important: false){ + $radius-value:map-get($uni-radius, $r) if($important, !important, null); + // Key exists within the $uni-radius variable + @if (map-has-key($uni-radius, $r) and $d){ + @if $d == t { + border-top-left-radius:$radius-value; + border-top-right-radius:$radius-value; + }@else if $d == r { + border-top-right-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == b { + border-bottom-left-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == l { + border-top-left-radius:$radius-value; + border-bottom-left-radius:$radius-value; + }@else if $d == tl { + border-top-left-radius:$radius-value; + }@else if $d == tr { + border-top-right-radius:$radius-value; + }@else if $d == br { + border-bottom-right-radius:$radius-value; + }@else if $d == bl { + border-bottom-left-radius:$radius-value; + } + }@else{ + border-radius:$radius-value; + } +} + +@each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $key} { + @include radius($key) + } + }@else{ + .uni-radius { + @include radius($key) + } + } +} + +@each $direction in t, r, b, l,tl, tr, br, bl { + @each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $direction}-#{"" + $key} { + @include radius($key,$direction,false) + } + }@else{ + .uni-radius-#{$direction} { + @include radius($key,$direction,false) + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_space.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_space.scss new file mode 100644 index 00000000..3c895289 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_space.scss @@ -0,0 +1,56 @@ + +@mixin fn($space,$direction,$size,$n) { + @if $n { + #{$space}-#{$direction}: #{$size*$uni-space-root}px + } @else { + #{$space}-#{$direction}: #{-$size*$uni-space-root}px + } +} +@mixin get-styles($direction,$i,$space,$n){ + @if $direction == t { + @include fn($space, top,$i,$n); + } + @if $direction == r { + @include fn($space, right,$i,$n); + } + @if $direction == b { + @include fn($space, bottom,$i,$n); + } + @if $direction == l { + @include fn($space, left,$i,$n); + } + @if $direction == x { + @include fn($space, left,$i,$n); + @include fn($space, right,$i,$n); + } + @if $direction == y { + @include fn($space, top,$i,$n); + @include fn($space, bottom,$i,$n); + } + @if $direction == a { + @if $n { + #{$space}:#{$i*$uni-space-root}px; + } @else { + #{$space}:#{-$i*$uni-space-root}px; + } + } +} + +@each $orientation in m,p { + $space: margin; + @if $orientation == m { + $space: margin; + } @else { + $space: padding; + } + @for $i from 0 through 16 { + @each $direction in t, r, b, l, x, y, a { + .uni-#{$orientation}#{$direction}-#{$i} { + @include get-styles($direction,$i,$space,true); + } + .uni-#{$orientation}#{$direction}-n#{$i} { + @include get-styles($direction,$i,$space,false); + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_styles.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_styles.scss new file mode 100644 index 00000000..689afec6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_styles.scss @@ -0,0 +1,167 @@ +/* #ifndef APP-NVUE */ + +$-color-white:#fff; +$-color-black:#000; +@mixin base-style($color) { + color: #fff; + background-color: $color; + border-color: mix($-color-black, $color, 8%); + &:not([hover-class]):active { + background: mix($-color-black, $color, 10%); + border-color: mix($-color-black, $color, 20%); + color: $-color-white; + outline: none; + } +} +@mixin is-color($color) { + @include base-style($color); + &[loading] { + @include base-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &[loading], + &:not([hover-class]):active { + color: $-color-white; + border-color: mix(darken($color,10%), $-color-white); + background-color: mix($color, $-color-white); + } + } + +} +@mixin base-plain-style($color) { + color:$color; + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 70%); + &:not([hover-class]):active { + background: mix($-color-white, $color, 80%); + color: $color; + outline: none; + border-color: mix($-color-white, $color, 50%); + } +} +@mixin is-plain($color){ + &[plain] { + @include base-plain-style($color); + &[loading] { + @include base-plain-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &:active { + color: mix($-color-white, $color, 40%); + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 80%); + } + } + } +} + + +.uni-btn { + margin: 5px; + color: #393939; + border:1px solid #ccc; + font-size: 16px; + font-weight: 200; + background-color: #F9F9F9; + // TODO 暂时处理边框隐藏一边的问题 + overflow: visible; + &::after{ + border: none; + } + + &:not([type]),&[type=default] { + color: #999; + &[loading] { + background: none; + &::before { + margin-right:5px; + } + } + + + + &[disabled]{ + color: mix($-color-white, #999, 60%); + &, + &[loading], + &:active { + color: mix($-color-white, #999, 60%); + background-color: mix($-color-white,$-color-black , 98%); + border-color: mix($-color-white, #999, 85%); + } + } + + &[plain] { + color: #999; + background: none; + border-color: $uni-border-1; + &:not([hover-class]):active { + background: none; + color: mix($-color-white, $-color-black, 80%); + border-color: mix($-color-white, $-color-black, 90%); + outline: none; + } + &[disabled]{ + &, + &[loading], + &:active { + background: none; + color: mix($-color-white, #999, 60%); + border-color: mix($-color-white, #999, 85%); + } + } + } + } + + &:not([hover-class]):active { + color: mix($-color-white, $-color-black, 50%); + } + + &[size=mini] { + font-size: 16px; + font-weight: 200; + border-radius: 8px; + } + + + + &.uni-btn-small { + font-size: 14px; + } + &.uni-btn-mini { + font-size: 12px; + } + + &.uni-btn-radius { + border-radius: 999px; + } + &[type=primary] { + @include is-color($uni-primary); + @include is-plain($uni-primary) + } + &[type=success] { + @include is-color($uni-success); + @include is-plain($uni-success) + } + &[type=error] { + @include is-color($uni-error); + @include is-plain($uni-error) + } + &[type=warning] { + @include is-color($uni-warning); + @include is-plain($uni-warning) + } + &[type=info] { + @include is-color($uni-info); + @include is-plain($uni-info) + } +} +/* #endif */ diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_text.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_text.scss new file mode 100644 index 00000000..a34d08f3 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_text.scss @@ -0,0 +1,24 @@ +@mixin get-styles($k,$c) { + @if $k == size or $k == weight{ + font-#{$k}:#{$c} + }@else{ + #{$k}:#{$c} + } +} + +@each $key, $child in $uni-headings { + /* #ifndef APP-NVUE */ + .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ + /* #ifdef APP-NVUE */ + .container .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ +} diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_variables.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_variables.scss new file mode 100644 index 00000000..557d3d7c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/setting/_variables.scss @@ -0,0 +1,146 @@ +// @use "sass:math"; +@import '../tools/functions.scss'; +// 间距基础倍数 +$uni-space-root: 2 !default; +// 边框半径默认值 +$uni-radius-root:5px !default; +$uni-radius: () !default; +// 边框半径断点 +$uni-radius: map-deep-merge( + ( + 0: 0, + // TODO 当前版本暂时不支持 sm 属性 + // 'sm': math.div($uni-radius-root, 2), + null: $uni-radius-root, + 'lg': $uni-radius-root * 2, + 'xl': $uni-radius-root * 6, + 'pill': 9999px, + 'circle': 50% + ), + $uni-radius +); +// 字体家族 +$body-font-family: 'Roboto', sans-serif !default; +// 文本 +$heading-font-family: $body-font-family !default; +$uni-headings: () !default; +$letterSpacing: -0.01562em; +$uni-headings: map-deep-merge( + ( + 'h1': ( + size: 32px, + weight: 300, + line-height: 50px, + // letter-spacing:-0.01562em + ), + 'h2': ( + size: 28px, + weight: 300, + line-height: 40px, + // letter-spacing: -0.00833em + ), + 'h3': ( + size: 24px, + weight: 400, + line-height: 32px, + // letter-spacing: normal + ), + 'h4': ( + size: 20px, + weight: 400, + line-height: 30px, + // letter-spacing: 0.00735em + ), + 'h5': ( + size: 16px, + weight: 400, + line-height: 24px, + // letter-spacing: normal + ), + 'h6': ( + size: 14px, + weight: 500, + line-height: 18px, + // letter-spacing: 0.0125em + ), + 'subtitle': ( + size: 12px, + weight: 400, + line-height: 20px, + // letter-spacing: 0.00937em + ), + 'body': ( + font-size: 14px, + font-weight: 400, + line-height: 22px, + // letter-spacing: 0.03125em + ), + 'caption': ( + 'size': 12px, + 'weight': 400, + 'line-height': 20px, + // 'letter-spacing': 0.03333em, + // 'text-transform': false + ) + ), + $uni-headings +); + + + +// 主色 +$uni-primary: #2979ff !default; +$uni-primary-disable:lighten($uni-primary,20%) !default; +$uni-primary-light: lighten($uni-primary,25%) !default; + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37 !default; +$uni-success-disable:lighten($uni-success,20%) !default; +$uni-success-light: lighten($uni-success,25%) !default; + +$uni-warning: #f3a73f !default; +$uni-warning-disable:lighten($uni-warning,20%) !default; +$uni-warning-light: lighten($uni-warning,25%) !default; + +$uni-error: #e43d33 !default; +$uni-error-disable:lighten($uni-error,20%) !default; +$uni-error-light: lighten($uni-error,25%) !default; + +$uni-info: #8f939c !default; +$uni-info-disable:lighten($uni-info,20%) !default; +$uni-info-light: lighten($uni-info,25%) !default; + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a !default; // 主要文字 +$uni-base-color: #6a6a6a !default; // 常规文字 +$uni-secondary-color: #909399 !default; // 次要文字 +$uni-extra-color: #c7c7c7 !default; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0 !default; +$uni-border-2: #EDEDED !default; +$uni-border-3: #DCDCDC !default; +$uni-border-4: #B9B9B9 !default; + +// 常规色 +$uni-black: #000000 !default; +$uni-white: #ffffff !default; +$uni-transparent: rgba($color: #000000, $alpha: 0) !default; + +// 背景色 +$uni-bg-color: #f7f7f7 !default; + +/* 水平间距 */ +$uni-spacing-sm: 8px !default; +$uni-spacing-base: 15px !default; +$uni-spacing-lg: 30px !default; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default; +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default; + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4) !default; diff --git a/yanzhu-ui-app/uni_modules/uni-scss/styles/tools/functions.scss b/yanzhu-ui-app/uni_modules/uni-scss/styles/tools/functions.scss new file mode 100644 index 00000000..ac6f63e5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/styles/tools/functions.scss @@ -0,0 +1,19 @@ +// 合并 map +@function map-deep-merge($parent-map, $child-map){ + $result: $parent-map; + @each $key, $child in $child-map { + $parent-has-key: map-has-key($result, $key); + $parent-value: map-get($result, $key); + $parent-type: type-of($parent-value); + $child-type: type-of($child); + $parent-is-map: $parent-type == map; + $child-is-map: $child-type == map; + + @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ + $result: map-merge($result, ( $key: $child )); + }@else { + $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); + } + } + @return $result; +}; diff --git a/yanzhu-ui-app/uni_modules/uni-scss/theme.scss b/yanzhu-ui-app/uni_modules/uni-scss/theme.scss new file mode 100644 index 00000000..80ee62f7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/theme.scss @@ -0,0 +1,31 @@ +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; +// 主色 +$uni-primary: #2979ff; +// 辅助色 +$uni-success: #4cd964; +// 警告色 +$uni-warning: #f0ad4e; +// 错误色 +$uni-error: #dd524d; +// 描述色 +$uni-info: #909399; +// 中性色 +$uni-main-color: #303133; +$uni-base-color: #606266; +$uni-secondary-color: #909399; +$uni-extra-color: #C0C4CC; +// 背景色 +$uni-bg-color: #f5f5f5; +// 边框颜色 +$uni-border-1: #DCDFE6; +$uni-border-2: #E4E7ED; +$uni-border-3: #EBEEF5; +$uni-border-4: #F2F6FC; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); diff --git a/yanzhu-ui-app/uni_modules/uni-scss/variables.scss b/yanzhu-ui-app/uni_modules/uni-scss/variables.scss new file mode 100644 index 00000000..1c062d42 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-scss/variables.scss @@ -0,0 +1,62 @@ +@import './styles/setting/_variables.scss'; +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; + +// 主色 +$uni-primary: #2979ff; +$uni-primary-disable:mix(#fff,$uni-primary,50%); +$uni-primary-light: mix(#fff,$uni-primary,80%); + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37; +$uni-success-disable:mix(#fff,$uni-success,50%); +$uni-success-light: mix(#fff,$uni-success,80%); + +$uni-warning: #f3a73f; +$uni-warning-disable:mix(#fff,$uni-warning,50%); +$uni-warning-light: mix(#fff,$uni-warning,80%); + +$uni-error: #e43d33; +$uni-error-disable:mix(#fff,$uni-error,50%); +$uni-error-light: mix(#fff,$uni-error,80%); + +$uni-info: #8f939c; +$uni-info-disable:mix(#fff,$uni-info,50%); +$uni-info-light: mix(#fff,$uni-info,80%); + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a; // 主要文字 +$uni-base-color: #6a6a6a; // 常规文字 +$uni-secondary-color: #909399; // 次要文字 +$uni-extra-color: #c7c7c7; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0; +$uni-border-2: #EDEDED; +$uni-border-3: #DCDCDC; +$uni-border-4: #B9B9B9; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); + +// 背景色 +$uni-bg-color: #f7f7f7; + +/* 水平间距 */ +$uni-spacing-sm: 8px; +$uni-spacing-base: 15px; +$uni-spacing-lg: 30px; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4); diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/changelog.md b/yanzhu-ui-app/uni_modules/uni-search-bar/changelog.md new file mode 100644 index 00000000..b41fdd3b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/changelog.md @@ -0,0 +1,33 @@ +## 1.2.3(2022-05-24) +- 新增 readonly 属性,组件只读 +## 1.2.2(2022-05-06) +- 修复 vue3 input 事件不生效的bug +## 1.2.1(2022-05-06) +- 修复 多余代码导致的bug +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-search-bar](https://uniapp.dcloud.io/component/uniui/uni-search-bar) +## 1.1.2(2021-08-30) +- 修复 value 属性与 modelValue 属性不兼容的Bug +## 1.1.1(2021-08-24) +- 新增 支持国际化 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.9(2021-05-12) +- 新增 项目示例地址 +## 1.0.8(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.7(2021-04-15) +- uni-ui 新增 uni-search-bar 的 focus 事件 + +## 1.0.6(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持双向绑定 +- 更改 input 事件的返回值,e={value:Number} --> e=value +- 新增 支持图标插槽 +- 新增 支持 clear、blur 事件 +- 新增 支持 focus 属性 +- 去掉组件背景色 diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json new file mode 100644 index 00000000..dd083a53 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "Search enter content" +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js new file mode 100644 index 00000000..de7509c8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json new file mode 100644 index 00000000..d4e5c120 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "请输入搜索内容" +} diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json new file mode 100644 index 00000000..318b6ef1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json @@ -0,0 +1,4 @@ +{ + "uni-search-bar.cancel": "cancel", + "uni-search-bar.placeholder": "請輸入搜索內容" +} diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue new file mode 100644 index 00000000..5a518a8c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue @@ -0,0 +1,298 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/package.json b/yanzhu-ui-app/uni_modules/uni-search-bar/package.json new file mode 100644 index 00000000..9352c574 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-search-bar", + "displayName": "uni-search-bar 搜索栏", + "version": "1.2.3", + "description": "搜索栏组件,通常用于搜索商品、文章等", + "keywords": [ + "uni-ui", + "uniui", + "搜索框", + "搜索栏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-search-bar/readme.md b/yanzhu-ui-app/uni_modules/uni-search-bar/readme.md new file mode 100644 index 00000000..253092f0 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-search-bar/readme.md @@ -0,0 +1,14 @@ + + +## SearchBar 搜索栏 + +> **组件名:uni-search-bar** +> 代码块: `uSearchBar` + + +搜索栏组件 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-search-bar) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-segmented-control/changelog.md b/yanzhu-ui-app/uni_modules/uni-segmented-control/changelog.md new file mode 100644 index 00000000..a44385d7 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-segmented-control/changelog.md @@ -0,0 +1,9 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-segmented-control](https://uniapp.dcloud.io/component/uniui/uni-segmented-control) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.5(2021-05-12) +- 新增 项目示例地址 +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue b/yanzhu-ui-app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue new file mode 100644 index 00000000..e8bb3e5a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-segmented-control/package.json b/yanzhu-ui-app/uni_modules/uni-segmented-control/package.json new file mode 100644 index 00000000..6cae41db --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-segmented-control/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-segmented-control", + "displayName": "uni-segmented-control 分段器", + "version": "1.2.0", + "description": "分段器由至少 2 个分段控件组成,用作不同视图的显示", + "keywords": [ + "uni-ui", + "uniui", + "分段器", + "segement", + "顶部选择" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-segmented-control/readme.md b/yanzhu-ui-app/uni_modules/uni-segmented-control/readme.md new file mode 100644 index 00000000..3527b03f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-segmented-control/readme.md @@ -0,0 +1,13 @@ + + +## SegmentedControl 分段器 +> **组件名:uni-segmented-control** +> 代码块: `uSegmentedControl` + + +用作不同视图的显示 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-segmented-control) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-steps/changelog.md b/yanzhu-ui-app/uni_modules/uni-steps/changelog.md new file mode 100644 index 00000000..cb9d3679 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-steps/changelog.md @@ -0,0 +1,16 @@ +## 1.1.1(2021-11-22) +- 修复 vue3中某些scss变量无法找到的问题 +## 1.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-steps](https://uniapp.dcloud.io/component/uniui/uni-steps) +## 1.0.8(2021-05-12) +- 新增 项目示例地址 +## 1.0.7(2021-05-06) +- 修复 uni-steps 横向布局时,多行文字高度不合理的 bug +## 1.0.6(2021-04-21) +- 优化 添加依赖 uni-icons, 导入后自动下载依赖 +## 1.0.5(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 + +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue b/yanzhu-ui-app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue new file mode 100644 index 00000000..a6c8f287 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-steps/package.json b/yanzhu-ui-app/uni_modules/uni-steps/package.json new file mode 100644 index 00000000..c687b40a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-steps/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-steps", + "displayName": "uni-steps 步骤条", + "version": "1.1.1", + "description": "步骤条组件,提供横向和纵向两种布局格式。", + "keywords": [ + "uni-ui", + "uniui", + "步骤条", + "时间轴" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-steps/readme.md b/yanzhu-ui-app/uni_modules/uni-steps/readme.md new file mode 100644 index 00000000..da7a4bfa --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-steps/readme.md @@ -0,0 +1,13 @@ + + +## Steps 步骤条 +> **组件名:uni-steps** +> 代码块: `uSteps` + + +步骤条,常用于显示进度 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-steps) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/changelog.md b/yanzhu-ui-app/uni_modules/uni-swipe-action/changelog.md new file mode 100644 index 00000000..c9164273 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/changelog.md @@ -0,0 +1,43 @@ +## 1.3.8(2023-04-13) +- 修复`uni-swipe-action`和`uni-swipe-action-item`不同时使用导致 closeOther 方法报错的 bug +## 1.3.7(2022-06-06) +- 修复 vue3 下使用组件不能正常运行的Bug +## 1.3.6(2022-05-31) +- 修复 h5端点击click触发两次的Bug +## 1.3.5(2022-05-23) +- 修复 isPC 找不到的Bug +## 1.3.4(2022-05-19) +- 修复 在 nvue 下 disabled 失效的bug +## 1.3.3(2022-03-31) +- 修复 按钮字体大小不能设置的bug +## 1.3.2(2022-03-16) +- 修复 h5和app端下报el错误的bug +## 1.3.1(2022-03-07) +- 修复 HBuilderX 1.4.X 版本中,h5和app端下报错的bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swipe-action](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +## 1.2.4(2021-08-20) +- 优化 close-all 方法 +## 1.2.3(2021-08-20) +- 新增 close-all 方法,关闭所有已打开的组件 +## 1.2.2(2021-08-17) +- 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件 +- 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 +- 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题 +## 1.2.1(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- 修复 跨页面修改组件数据 ,导致不能滑动的问题 +## 1.1.10(2021-06-17) +- 修复 按钮点击执行两次的bug +## 1.1.9(2021-05-12) +- 新增 项目示例地址 +## 1.1.8(2021-03-26) +- 修复 微信小程序 nv_navigator is not defined 报错的bug +## 1.1.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 左侧滑动 +- 新增 插槽使用方式 +- 新增 threshold 属性,可以控制滑动缺省值 +- 优化 长列表滚动性能 +- 修复 滚动页面时触发组件滑动的Bug diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js new file mode 100644 index 00000000..707e432e --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js @@ -0,0 +1,302 @@ +let bindIngXMixins = {} + +// #ifdef APP-NVUE +const BindingX = uni.requireNativePlugin('bindingx'); +const dom = uni.requireNativePlugin('dom'); +const animation = uni.requireNativePlugin('animation'); + +bindIngXMixins = { + data() { + return {} + }, + + watch: { + show(newVal) { + if (this.autoClose) return + if (this.stop) return + this.stop = true + if (newVal) { + this.open(newVal) + } else { + this.close() + } + }, + leftOptions() { + this.getSelectorQuery() + this.init() + }, + rightOptions(newVal) { + this.init() + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.box = this.getEl(this.$refs['selector-box--hock']) + this.selector = this.getEl(this.$refs['selector-content--hock']); + this.leftButton = this.getEl(this.$refs['selector-left-button--hock']); + this.rightButton = this.getEl(this.$refs['selector-right-button--hock']); + this.init() + }, + // beforeDestroy() { + // this.swipeaction.children.forEach((item, index) => { + // if (item === this) { + // this.swipeaction.children.splice(index, 1) + // } + // }) + // }, + methods: { + init() { + this.$nextTick(() => { + this.x = 0 + this.button = { + show: false + } + setTimeout(() => { + this.getSelectorQuery() + }, 200) + }) + }, + onClick(index, item, position) { + this.$emit('click', { + content: item, + index, + position + }) + }, + touchstart(e) { + // fix by mehaotian 禁止滑动 + if (this.disabled) return + // 每次只触发一次,避免多次监听造成闪烁 + if (this.stop) return + this.stop = true + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + let expression = this.range(this.x, -rightWidth, leftWidth) + let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0) + let rightExpression = this.range(this.x + rightWidth, 0, rightWidth) + + this.eventpan = BindingX.bind({ + anchor: this.box, + eventType: 'pan', + props: [{ + element: this.selector, + property: 'transform.translateX', + expression + }, { + element: this.leftButton, + property: 'transform.translateX', + expression: leftExpression + }, { + element: this.rightButton, + property: 'transform.translateX', + expression: rightExpression + }, ] + }, (e) => { + // nope + if (e.state === 'end') { + this.x = e.deltaX + this.x; + this.isclick = true + this.bindTiming(e.deltaX) + } + }); + }, + touchend(e) { + if (this.isopen !== 'none' && !this.isclick) { + this.open('none') + } + }, + bindTiming(x) { + const left = this.x + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + const threshold = this.threshold + if (!this.isopen || this.isopen === 'none') { + if (left > threshold) { + this.open('left') + } else if (left < -threshold) { + this.open('right') + } else { + this.open('none') + } + } else { + if ((x > -leftWidth && x < 0) || x > rightWidth) { + if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) { + this.open('left') + } else { + this.open('none') + } + } else { + if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) { + this.open('right') + } else { + this.open('none') + } + } + } + }, + + /** + * 移动范围 + * @param {Object} num + * @param {Object} mix + * @param {Object} max + */ + range(num, mix, max) { + return `min(max(x+${num}, ${mix}), ${max})` + }, + + /** + * 开启swipe + */ + open(type) { + this.animation(type) + }, + + /** + * 关闭swipe + */ + close() { + this.animation('none') + }, + + /** + * 开启关闭动画 + * @param {Object} type + */ + animation(type) { + const time = 300 + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + if (this.eventpan && this.eventpan.token) { + BindingX.unbind({ + token: this.eventpan.token, + eventType: 'pan' + }) + } + + switch (type) { + case 'left': + Promise.all([ + this.move(this.selector, leftWidth), + this.move(this.leftButton, 0), + this.move(this.rightButton, rightWidth * 2) + ]).then(() => { + this.setEmit(leftWidth, type) + }) + break + case 'right': + Promise.all([ + this.move(this.selector, -rightWidth), + this.move(this.leftButton, -leftWidth * 2), + this.move(this.rightButton, 0) + ]).then(() => { + this.setEmit(-rightWidth, type) + }) + break + default: + Promise.all([ + this.move(this.selector, 0), + this.move(this.leftButton, -leftWidth), + this.move(this.rightButton, rightWidth) + ]).then(() => { + this.setEmit(0, type) + }) + + } + }, + setEmit(x, type) { + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + this.isopen = this.isopen || 'none' + this.stop = false + this.isclick = false + // 只有状态不一致才会返回结果 + if (this.isopen !== type && this.x !== x) { + if (type === 'left' && leftWidth > 0) { + this.$emit('change', 'left') + } + if (type === 'right' && rightWidth > 0) { + this.$emit('change', 'right') + } + if (type === 'none') { + this.$emit('change', 'none') + } + } + this.x = x + this.isopen = type + }, + move(ref, value) { + return new Promise((resolve, reject) => { + animation.transition(ref, { + styles: { + transform: `translateX(${value})`, + }, + duration: 150, //ms + timingFunction: 'linear', + needLayout: false, + delay: 0 //ms + }, function(res) { + resolve(res) + }) + }) + + }, + + /** + * 获取ref + * @param {Object} el + */ + getEl(el) { + return el.ref + }, + /** + * 获取节点信息 + */ + getSelectorQuery() { + Promise.all([ + this.getDom('left'), + this.getDom('right'), + ]).then((data) => { + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + + if (show === 'none') { + // this.close() + } else { + this.open(show) + } + + }) + + }, + getDom(str) { + return new Promise((resolve, reject) => { + dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => { + if (data) { + this.button[str] = data.size + resolve(data) + } else { + reject() + } + }) + }) + } + } +} + +// #endif + +export default bindIngXMixins diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js new file mode 100644 index 00000000..917cb489 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js @@ -0,0 +1,12 @@ +export function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (let v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js new file mode 100644 index 00000000..35c796bd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js @@ -0,0 +1,195 @@ +export default { + data() { + return { + x: 0, + transition: false, + width: 0, + viewWidth: 0, + swipeShow: 0 + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + if (newVal && newVal !== 'none') { + this.transition = true + this.open(newVal) + } else { + this.close() + } + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.isopen = false + setTimeout(() => { + this.getQuerySelect() + }, 50) + }, + methods: { + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + /** + * 移动触发 + * @param {Object} e + */ + onChange(e) { + this.moveX = e.detail.x + this.isclose = false + }, + touchstart(e) { + this.transition = false + this.isclose = true + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + touchmove(e) {}, + touchend(e) { + // 0的位置什么都不执行 + if (this.isclose && this.isopen === 'none') return + if (this.isclose && this.isopen !== 'none') { + this.transition = true + this.close() + } else { + this.move(this.moveX + this.leftWidth) + } + }, + + /** + * 移动 + * @param {Object} moveX + */ + move(moveX) { + // 打开关闭的处理逻辑不太一样 + this.transition = true + // 未打开状态 + if (!this.isopen || this.isopen === 'none') { + if (moveX > this.threshold) { + this.open('left') + } else if (moveX < -this.threshold) { + this.open('right') + } else { + this.close() + } + } else { + if (moveX < 0 && moveX < this.rightWidth) { + const rightX = this.rightWidth + moveX + if (rightX < this.threshold) { + this.open('right') + } else { + this.close() + } + } else if (moveX > 0 && moveX < this.leftWidth) { + const leftX = this.leftWidth - moveX + if (leftX < this.threshold) { + this.open('left') + } else { + this.close() + } + } + + } + + }, + + /** + * 打开 + */ + open(type) { + this.x = this.moveX + this.animation(type) + }, + + /** + * 关闭 + */ + close() { + this.x = this.moveX + // TODO 解决 x 值不更新的问题,所以会多触发一次 nextTick ,待优化 + this.$nextTick(() => { + this.x = -this.leftWidth + if (this.isopen !== 'none') { + this.$emit('change', 'none') + } + this.isopen = 'none' + }) + }, + + /** + * 执行结束动画 + * @param {Object} type + */ + animation(type) { + this.$nextTick(() => { + if (type === 'left') { + this.x = 0 + } else { + this.x = -this.rightWidth - this.leftWidth + } + + if (this.isopen !== type) { + this.$emit('change', type) + } + this.isopen = type + }) + + }, + getSlide(x) {}, + getQuerySelect() { + const query = uni.createSelectorQuery().in(this); + query.selectAll('.movable-view--hock').boundingClientRect(data => { + this.leftWidth = data[1].width + this.rightWidth = data[2].width + this.width = data[0].width + this.viewWidth = this.width + this.rightWidth + this.leftWidth + if (this.leftWidth === 0) { + // TODO 疑似bug ,初始化的时候如果x 是0,会导致移动位置错误,所以让元素超出一点 + this.x = -0.1 + } else { + this.x = -this.leftWidth + } + this.moveX = this.x + this.$nextTick(() => { + this.swipeShow = 1 + }) + + if (!this.buttonWidth) { + this.disabledView = true + } + + if (this.autoClose) return + if (this.show !== 'none') { + this.transition = true + this.open(this.shows) + } + }).exec(); + + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js new file mode 100644 index 00000000..d389bce4 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js @@ -0,0 +1,260 @@ +let otherMixins = {} + +// #ifndef APP-PLUS|| MP-WEIXIN || H5 +const MIN_DISTANCE = 10; +otherMixins = { + data() { + // TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug + const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}` + return { + uniShow: false, + left: 0, + buttonShow: 'none', + ani: false, + moveLeft: '', + elClass + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + this.openState(newVal) + }, + left() { + this.moveLeft = `translateX(${this.left}px)` + }, + buttonShow(newVal) { + if (this.autoClose) return + this.openState(newVal) + }, + leftOptions() { + this.init() + }, + rightOptions() { + this.init() + } + }, + mounted() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + this.init() + }, + methods: { + init() { + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.getSelectorQuery() + }, 100) + // 移动距离 + this.left = 0 + this.x = 0 + }, + + closeSwipe(e) { + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + touchstart(e) { + if (this.disabled) return + this.ani = false + this.x = this.left || 0 + this.stopTouchStart(e) + this.autoClose && this.closeSwipe() + }, + touchmove(e) { + if (this.disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e); + if (this.direction !== 'horizontal') { + return; + } + this.move(this.x + this.deltaX) + return false + }, + touchend() { + if (this.disabled) return + this.moveDirection(this.left) + }, + /** + * 设置移动距离 + * @param {Object} value + */ + move(value) { + value = value || 0 + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + // 获取可滑动范围 + this.left = this.range(value, -rightWidth, leftWidth); + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + */ + moveDirection(left) { + const threshold = this.threshold + const isopen = this.isopen || 'none' + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + if (this.deltaX === 0) { + this.openState('none') + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > + 0 && rightWidth + + left < threshold)) { + // right + this.openState('right') + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > + 0 && + leftWidth - left < threshold)) { + // left + this.openState('left') + } else { + // default + this.openState('none') + } + }, + + /** + * 开启状态 + * @param {Boolean} type + */ + openState(type) { + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + let left = '' + this.isopen = this.isopen ? this.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + + if (this.isopen !== type) { + this.throttle = true + this.$emit('change', type) + } + + this.isopen = type + // 添加动画类 + this.ani = true + this.$nextTick(() => { + this.move(left) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 + }, + close() { + this.openState('none') + }, + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus() { + this.direction = ''; + this.deltaX = 0; + this.deltaY = 0; + this.offsetX = 0; + this.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event) { + this.resetTouchStatus(); + const touch = event.touches[0]; + this.startX = touch.clientX; + this.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event) { + const touch = event.touches[0]; + this.deltaX = touch.clientX - this.startX; + this.deltaY = touch.clientY - this.startY; + this.offsetX = Math.abs(this.deltaX); + this.offsetY = Math.abs(this.deltaY); + this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY); + }, + + getSelectorQuery() { + const views = uni.createSelectorQuery().in(this) + views + .selectAll('.' + this.elClass) + .boundingClientRect(data => { + if (data.length === 0) return + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + this.leftWidth = data[0].width || 0 + this.rightWidth = data[1].width || 0 + this.buttonShow = show + }) + .exec() + } + } +} + +// #endif + +export default otherMixins diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js new file mode 100644 index 00000000..08de1c9c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js @@ -0,0 +1,84 @@ +let mpMixins = {} +let is_pc = null +// #ifdef H5 +import { + isPC +} from "./isPC" +is_pc = isPC() +// #endif +// #ifdef APP-VUE|| MP-WEIXIN || H5 + +mpMixins = { + data() { + return { + is_show: 'none' + } + }, + watch: { + show(newVal) { + this.is_show = this.show + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.is_show = this.show + }, + methods: { + // wxs 中调用 + closeSwipe(e) { + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + + change(e) { + this.$emit('change', e.open) + if (this.is_show !== e.open) { + this.is_show = e.open + } + }, + + appTouchStart(e) { + if (is_pc) return + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + if (is_pc) return + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + onClickForPC(index, item, position) { + if (!is_pc) return + // #ifdef H5 + this.$emit('click', { + content: item, + index, + position + }) + // #endif + } + } +} + +// #endif +export default mpMixins diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js new file mode 100644 index 00000000..78f0ec60 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js @@ -0,0 +1,270 @@ +const MIN_DISTANCE = 10; +export default { + showWatch(newVal, oldVal, ownerInstance, instance, self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + if (!$el) return + this.getDom(instance, ownerInstance, self) + if (newVal && newVal !== 'none') { + this.openState(newVal, instance, ownerInstance, self) + return + } + + if (state.left) { + this.openState('none', instance, ownerInstance, self) + } + this.resetTouchStatus(instance, self) + }, + + /** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ + touchstart(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state; + this.getDom(instance, ownerInstance, self) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + this.stopTouchStart(e, ownerInstance, self) + }, + + /** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchmove(e, ownerInstance, self) { + let instance = e.instance; + // 删除之后已经那不到实例了 + if (!instance) return; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e, self); + if (state.direction !== 'horizontal') { + return; + } + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + let x = state.x + state.deltaX + this.move(x, instance, ownerInstance, self) + }, + + /** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchend(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + this.moveDirection(state.left, instance, ownerInstance, self) + + }, + + /** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ + move(value, instance, ownerInstance, self) { + value = value || 0 + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = this.range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + + }, + + /** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ + getDom(instance, ownerInstance, self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + var leftDom = $el.querySelector('.button-group--left') + var rightDom = $el.querySelector('.button-group--right') + + state.leftWidth = leftDom.offsetWidth || 0 + state.rightWidth = rightDom.offsetWidth || 0 + state.threshold = instance.getDataset().threshold + }, + + getDisabledType(value) { + return (typeof(value) === 'string' ? JSON.parse(value) : value) || false; + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + + + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ + moveDirection(left, ins, ownerInstance, self) { + var state = self.state + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + this.openState('none', ins, ownerInstance, self) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + this.openState('right', ins, ownerInstance, self) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + this.openState('left', ins, ownerInstance, self) + } else { + // default + this.openState('none', ins, ownerInstance, self) + } + }, + + + /** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ + openState(type, ins, ownerInstance, self) { + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + let left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(() => { + ins.addClass('ani'); + this.move(left, ins, ownerInstance, self) + }) + }, + + + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus(instance, self) { + let state = self.state; + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event, ownerInstance, self) { + let instance = event.instance; + let state = self.state + this.resetTouchStatus(instance, self); + var touch = event.touches[0]; + state.startX = touch.clientX; + state.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event, self) { + let instance = event.instance; + let state = self.state; + let touch = event.touches[0]; + + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || this.getDirection(state.offsetX, state.offsetY); + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue new file mode 100644 index 00000000..d79c2979 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue @@ -0,0 +1,347 @@ + + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs new file mode 100644 index 00000000..b394244f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs @@ -0,0 +1,341 @@ +var MIN_DISTANCE = 10; + +/** + * 判断当前是否为H5、app-vue + */ +var IS_HTML5 = false +if (typeof window === 'object') IS_HTML5 = true + +/** + * 监听页面内值的变化,主要用于动态开关swipe-action + * @param {Object} newValue + * @param {Object} oldValue + * @param {Object} ownerInstance + * @param {Object} instance + */ +function showWatch(newVal, oldVal, ownerInstance, instance) { + var state = instance.getState() + getDom(instance, ownerInstance) + if (newVal && newVal !== 'none') { + openState(newVal, instance, ownerInstance) + return + } + + if (state.left) { + openState('none', instance, ownerInstance) + } + resetTouchStatus(instance) +} + +/** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ +function touchstart(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState(); + getDom(instance, ownerInstance) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + stopTouchStart(e, ownerInstance) +} + +/** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchmove(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 是否可以滑动页面 + stopTouchMove(e); + if (state.direction !== 'horizontal') { + return; + } + + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + + move(state.x + state.deltaX, instance, ownerInstance) +} + +/** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchend(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + moveDirection(state.left, instance, ownerInstance) + +} + +/** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ +function move(value, instance, ownerInstance) { + value = value || 0 + var state = instance.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + +} + +/** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ +function getDom(instance, ownerInstance) { + var state = instance.getState() + var leftDom = ownerInstance.selectComponent('.button-group--left') + var rightDom = ownerInstance.selectComponent('.button-group--right') + var leftStyles = { + width: 0 + } + var rightStyles = { + width: 0 + } + leftStyles = leftDom.getBoundingClientRect() + rightStyles = rightDom.getBoundingClientRect() + + state.leftWidth = leftStyles.width || 0 + state.rightWidth = rightStyles.width || 0 + state.threshold = instance.getDataset().threshold +} + +/** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ +function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} + + +/** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ +function moveDirection(left, ins, ownerInstance) { + var state = ins.getState() + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + openState('none', ins, ownerInstance) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + openState('right', ins, ownerInstance) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + openState('left', ins, ownerInstance) + } else { + // default + openState('none', ins, ownerInstance) + } +} + + +/** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ +function openState(type, ins, ownerInstance) { + var state = ins.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + var left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(function() { + ins.addClass('ani'); + move(left, ins, ownerInstance) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 +} + + +function getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; +} + +/** + * 重置滑动状态 + * @param {Object} event + */ +function resetTouchStatus(instance) { + var state = instance.getState(); + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; +} + +/** + * 设置滑动开始位置 + * @param {Object} event + */ +function stopTouchStart(event) { + var instance = event.instance; + var state = instance.getState(); + resetTouchStatus(instance); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.startX = touch.clientX; + state.startY = touch.clientY; +} + +/** + * 滑动中,是否禁止打开 + * @param {Object} event + */ +function stopTouchMove(event) { + var instance = event.instance; + var state = instance.getState(); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || getDirection(state.offsetX, state.offsetY); +} + +function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (var v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} + +var movable = false + +function mousedown(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchstart(e, ins) + movable = true +} + +function mousemove(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + if (!movable) return + touchmove(e, ins) +} + +function mouseup(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchend(e, ins) + movable = false +} + +function mouseleave(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + movable = false +} + +module.exports = { + showWatch: showWatch, + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + mousedown: mousedown, + mousemove: mousemove, + mouseup: mouseup, + mouseleave: mouseleave +} diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue new file mode 100644 index 00000000..49717824 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/package.json b/yanzhu-ui-app/uni_modules/uni-swipe-action/package.json new file mode 100644 index 00000000..47651a62 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-swipe-action", + "displayName": "uni-swipe-action 滑动操作", + "version": "1.3.8", + "description": "SwipeAction 滑动操作操作组件", + "keywords": [ + "", + "uni-ui", + "uniui", + "滑动删除", + "侧滑删除" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/yanzhu-ui-app/uni_modules/uni-swipe-action/readme.md b/yanzhu-ui-app/uni_modules/uni-swipe-action/readme.md new file mode 100644 index 00000000..93a5cac6 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swipe-action/readme.md @@ -0,0 +1,11 @@ + + +## SwipeAction 滑动操作 +> **组件名:uni-swipe-action** +> 代码块: `uSwipeAction`、`uSwipeActionItem` + + +通过滑动触发选项的容器 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-swiper-dot/changelog.md b/yanzhu-ui-app/uni_modules/uni-swiper-dot/changelog.md new file mode 100644 index 00000000..85cf54d2 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swiper-dot/changelog.md @@ -0,0 +1,12 @@ +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swiper-dot](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.6(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.5(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 clickItem 事件,支持指示点控制轮播 +- 新增 支持 pc 可用 diff --git a/yanzhu-ui-app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue b/yanzhu-ui-app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue new file mode 100644 index 00000000..46eb8c1f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-swiper-dot/package.json b/yanzhu-ui-app/uni_modules/uni-swiper-dot/package.json new file mode 100644 index 00000000..f2dd8d2a --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swiper-dot/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-swiper-dot", + "displayName": "uni-swiper-dot 轮播图指示点", + "version": "1.2.0", + "description": "自定义轮播图指示点组件", + "keywords": [ + "uni-ui", + "uniui", + "轮播图指示点", + "dot", + "swiper" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-swiper-dot/readme.md b/yanzhu-ui-app/uni_modules/uni-swiper-dot/readme.md new file mode 100644 index 00000000..7d397e2c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-swiper-dot/readme.md @@ -0,0 +1,11 @@ + + +## SwiperDot 轮播图指示点 +> **组件名:uni-swiper-dot** +> 代码块: `uSwiperDot` + + +自定义轮播图指示点 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-table/changelog.md b/yanzhu-ui-app/uni_modules/uni-table/changelog.md new file mode 100644 index 00000000..9f87c67c --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/changelog.md @@ -0,0 +1,27 @@ +## 1.2.3(2023-03-28) +- 修复 在vue3模式下可能会出现错误的问题 +## 1.2.2(2022-11-29) +- 优化 主题样式 +## 1.2.1(2022-06-06) +- 修复 微信小程序存在无使用组件的问题 +## 1.2.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-table](https://uniapp.dcloud.io/component/uniui/uni-table) +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-07-08) +- 新增 uni-th 支持 date 日期筛选范围 +## 1.0.6(2021-07-05) +- 新增 uni-th 支持 range 筛选范围 +## 1.0.5(2021-06-28) +- 新增 uni-th 筛选功能 +## 1.0.4(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.3(2021-04-16) +- 新增 sortable 属性,是否开启单列排序 +- 优化 表格多选逻辑 +## 1.0.2(2021-03-22) +- uni-tr 添加 disabled 属性,用于 type=selection 时,设置某行是否可由全选按钮控制 +## 1.0.1(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-table/uni-table.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-table/uni-table.vue new file mode 100644 index 00000000..21d9527f --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-table/uni-table.vue @@ -0,0 +1,455 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue new file mode 100644 index 00000000..fbe1bdcb --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-td/uni-td.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-td/uni-td.vue new file mode 100644 index 00000000..9ce93e93 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-td/uni-td.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue new file mode 100644 index 00000000..df22a714 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue @@ -0,0 +1,511 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/uni-th.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/uni-th.vue new file mode 100644 index 00000000..14889dd8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-th/uni-th.vue @@ -0,0 +1,285 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-thead/uni-thead.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-thead/uni-thead.vue new file mode 100644 index 00000000..0dd18cd8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-thead/uni-thead.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue new file mode 100644 index 00000000..1089187e --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/uni-tr.vue b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/uni-tr.vue new file mode 100644 index 00000000..f9b96716 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/components/uni-tr/uni-tr.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/en.json b/yanzhu-ui-app/uni_modules/uni-table/i18n/en.json new file mode 100644 index 00000000..e32023cc --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/en.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Reset", + "filter-dropdown.search": "Search", + "filter-dropdown.submit": "Submit", + "filter-dropdown.filter": "Filter", + "filter-dropdown.gt": "Greater or equal to", + "filter-dropdown.lt": "Less than or equal to", + "filter-dropdown.date": "Date" +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/es.json b/yanzhu-ui-app/uni_modules/uni-table/i18n/es.json new file mode 100644 index 00000000..9afd04bb --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/es.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Reiniciar", + "filter-dropdown.search": "Búsqueda", + "filter-dropdown.submit": "Entregar", + "filter-dropdown.filter": "Filtrar", + "filter-dropdown.gt": "Mayor o igual a", + "filter-dropdown.lt": "Menos que o igual a", + "filter-dropdown.date": "Fecha" +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/fr.json b/yanzhu-ui-app/uni_modules/uni-table/i18n/fr.json new file mode 100644 index 00000000..b0062371 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/fr.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "Réinitialiser", + "filter-dropdown.search": "Chercher", + "filter-dropdown.submit": "Soumettre", + "filter-dropdown.filter": "Filtre", + "filter-dropdown.gt": "Supérieur ou égal à", + "filter-dropdown.lt": "Inférieur ou égal à", + "filter-dropdown.date": "Date" +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/index.js b/yanzhu-ui-app/uni_modules/uni-table/i18n/index.js new file mode 100644 index 00000000..2469dd02 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/index.js @@ -0,0 +1,12 @@ +import en from './en.json' +import es from './es.json' +import fr from './fr.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + es, + fr, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hans.json b/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hans.json new file mode 100644 index 00000000..862af179 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "重置", + "filter-dropdown.search": "搜索", + "filter-dropdown.submit": "确定", + "filter-dropdown.filter": "筛选", + "filter-dropdown.gt": "大于等于", + "filter-dropdown.lt": "小于等于", + "filter-dropdown.date": "日期范围" +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hant.json b/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hant.json new file mode 100644 index 00000000..64f80615 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/i18n/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "filter-dropdown.reset": "重置", + "filter-dropdown.search": "搜索", + "filter-dropdown.submit": "確定", + "filter-dropdown.filter": "篩選", + "filter-dropdown.gt": "大於等於", + "filter-dropdown.lt": "小於等於", + "filter-dropdown.date": "日期範圍" +} diff --git a/yanzhu-ui-app/uni_modules/uni-table/package.json b/yanzhu-ui-app/uni_modules/uni-table/package.json new file mode 100644 index 00000000..7c2f91cd --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-table", + "displayName": "uni-table 表格", + "version": "1.2.3", + "description": "表格组件,多用于展示多条结构类似的数据,如", + "keywords": [ + "uni-ui", + "uniui", + "table", + "表格" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-datetime-picker"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "n", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-table/readme.md b/yanzhu-ui-app/uni_modules/uni-table/readme.md new file mode 100644 index 00000000..bb08c791 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-table/readme.md @@ -0,0 +1,13 @@ + + +## Table 表单 +> 组件名:``uni-table``,代码块: `uTable`。 + +用于展示多条结构类似的数据 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-table) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-tag/changelog.md b/yanzhu-ui-app/uni_modules/uni-tag/changelog.md new file mode 100644 index 00000000..c0c5839b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tag/changelog.md @@ -0,0 +1,21 @@ +## 2.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-tag](https://uniapp.dcloud.io/component/uniui/uni-tag) +## 2.0.0(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +- 移除 插槽 +- 移除 type 属性的 royal 选项 +## 1.1.1(2021-08-11) +- type 不是 default 时,size 为 small 字体大小显示不正确 +## 1.1.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.0.7(2021-06-18) +- 修复 uni-tag 在字节跳动小程序上 css 类名编译错误的 bug +## 1.0.6(2021-06-04) +- 修复 未定义 sass 变量 "$uni-color-royal" 的bug +## 1.0.5(2021-05-10) +- 修复 royal 类型无效的bug +- 修复 uni-tag 宽度不自适应的bug +- 新增 uni-tag 支持属性 custom-style 自定义样式 +## 1.0.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue b/yanzhu-ui-app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue new file mode 100644 index 00000000..6378a0b9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue @@ -0,0 +1,252 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-tag/package.json b/yanzhu-ui-app/uni_modules/uni-tag/package.json new file mode 100644 index 00000000..18780886 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tag/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-tag", + "displayName": "uni-tag 标签", + "version": "2.1.0", + "description": "Tag 组件,用于展示1个或多个文字标签,可点击切换选中、不选中的状态。", + "keywords": [ + "uni-ui", + "uniui", + "", + "tag", + "标签" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-tag/readme.md b/yanzhu-ui-app/uni_modules/uni-tag/readme.md new file mode 100644 index 00000000..6e78ff5e --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tag/readme.md @@ -0,0 +1,13 @@ + + +## Tag 标签 +> **组件名:uni-tag** +> 代码块: `uTag` + + +用于展示1个或多个文字标签,可点击切换选中、不选中的状态 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tag) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/yanzhu-ui-app/uni_modules/uni-title/changelog.md b/yanzhu-ui-app/uni_modules/uni-title/changelog.md new file mode 100644 index 00000000..76262165 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-title/changelog.md @@ -0,0 +1,10 @@ +## 1.1.1(2022-05-19) +- 修改组件描述 +## 1.1.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-title](https://uniapp.dcloud.io/component/uniui/uni-title) +## 1.0.2(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的Bug +## 1.0.1(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-title/components/uni-title/uni-title.vue b/yanzhu-ui-app/uni_modules/uni-title/components/uni-title/uni-title.vue new file mode 100644 index 00000000..bf4f9265 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-title/components/uni-title/uni-title.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-title/package.json b/yanzhu-ui-app/uni_modules/uni-title/package.json new file mode 100644 index 00000000..2249f5a1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-title/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-title", + "displayName": "uni-title 章节标题", + "version": "1.1.1", + "description": "章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题", + "keywords": [ + "uni-ui", + "uniui", + "标题", + "章节", + "章节标题", + "" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-title/readme.md b/yanzhu-ui-app/uni_modules/uni-title/readme.md new file mode 100644 index 00000000..0e60b1b9 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-title/readme.md @@ -0,0 +1,14 @@ + + +## Title 标题 +> **组件名:uni-title** +> 代码块: `uTitle` + + +章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-title) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + diff --git a/yanzhu-ui-app/uni_modules/uni-tooltip/changelog.md b/yanzhu-ui-app/uni_modules/uni-tooltip/changelog.md new file mode 100644 index 00000000..00f1572d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tooltip/changelog.md @@ -0,0 +1,10 @@ +## 0.2.1(2022-05-09) +- 修复 content 为空时仍然弹出的bug +## 0.2.0(2022-05-07) +**注意:破坏性更新** +- 更新 text 属性变更为 content +- 更新 移除 width 属性 +## 0.1.1(2022-04-27) +- 修复 组件根 text 嵌套组件 warning +## 0.1.0(2022-04-21) +- 初始化 diff --git a/yanzhu-ui-app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue b/yanzhu-ui-app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue new file mode 100644 index 00000000..ffbb6fa5 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue @@ -0,0 +1,68 @@ + + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-tooltip/package.json b/yanzhu-ui-app/uni_modules/uni-tooltip/package.json new file mode 100644 index 00000000..e88ecf8d --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tooltip/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-tooltip", + "displayName": "uni-tooltip 提示文字", + "version": "0.2.1", + "description": "Tooltip 提示文字", + "keywords": [ + "uni-tooltip", + "uni-ui", + "tooltip", + "tip", + "文字提示" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无 ", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-tooltip/readme.md b/yanzhu-ui-app/uni_modules/uni-tooltip/readme.md new file mode 100644 index 00000000..faafa2ec --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-tooltip/readme.md @@ -0,0 +1,8 @@ +## Badge 数字角标 +> **组件名:uni-tooltip** +> 代码块: `uTooltip` + +数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tooltip) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/yanzhu-ui-app/uni_modules/uni-transition/changelog.md b/yanzhu-ui-app/uni_modules/uni-transition/changelog.md new file mode 100644 index 00000000..b1a824b8 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-transition/changelog.md @@ -0,0 +1,20 @@ +## 1.3.1(2021-11-23) +- 修复 init 方法初始化问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) +## 1.2.1(2021-09-27) +- 修复 init 方法不生效的 Bug +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.1(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的 Bug +## 1.1.0(2021-04-22) +- 新增 通过方法自定义动画 +- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 +- 优化 动画触发逻辑,使动画更流畅 +- 优化 支持单独的动画类型 +- 优化 文档示例 +## 1.0.2(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/createAnimation.js new file mode 100644 index 00000000..8f89b185 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/createAnimation.js @@ -0,0 +1,131 @@ +// const defaultOption = { +// duration: 300, +// timingFunction: 'linear', +// delay: 0, +// transformOrigin: '50% 50% 0' +// } +// #ifdef APP-NVUE +const nvueAnimation = uni.requireNativePlugin('animation') +// #endif +class MPAnimation { + constructor(options, _this) { + this.options = options + // 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误 + this.animation = uni.createAnimation({ + ...options + }) + this.currentStepAnimates = {} + this.next = 0 + this.$ = _this + + } + + _nvuePushAnimates(type, args) { + let aniObj = this.currentStepAnimates[this.next] + let styles = {} + if (!aniObj) { + styles = { + styles: {}, + config: {} + } + } else { + styles = aniObj + } + if (animateTypes1.includes(type)) { + if (!styles.styles.transform) { + styles.styles.transform = '' + } + let unit = '' + if(type === 'rotate'){ + unit = 'deg' + } + styles.styles.transform += `${type}(${args+unit}) ` + } else { + styles.styles[type] = `${args}` + } + this.currentStepAnimates[this.next] = styles + } + _animateRun(styles = {}, config = {}) { + let ref = this.$.$refs['ani'].ref + if (!ref) return + return new Promise((resolve, reject) => { + nvueAnimation.transition(ref, { + styles, + ...config + }, res => { + resolve() + }) + }) + } + + _nvueNextAnimate(animates, step = 0, fn) { + let obj = animates[step] + if (obj) { + let { + styles, + config + } = obj + this._animateRun(styles, config).then(() => { + step += 1 + this._nvueNextAnimate(animates, step, fn) + }) + } else { + this.currentStepAnimates = {} + typeof fn === 'function' && fn() + this.isEnd = true + } + } + + step(config = {}) { + // #ifndef APP-NVUE + this.animation.step(config) + // #endif + // #ifdef APP-NVUE + this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) + this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin + this.next++ + // #endif + return this + } + + run(fn) { + // #ifndef APP-NVUE + this.$.animationData = this.animation.export() + this.$.timer = setTimeout(() => { + typeof fn === 'function' && fn() + }, this.$.durationTime) + // #endif + // #ifdef APP-NVUE + this.isEnd = false + let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref + if(!ref) return + this._nvueNextAnimate(this.currentStepAnimates, 0, fn) + this.next = 0 + // #endif + } +} + + +const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', + 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', + 'translateZ' +] +const animateTypes2 = ['opacity', 'backgroundColor'] +const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'] +animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { + MPAnimation.prototype[type] = function(...args) { + // #ifndef APP-NVUE + this.animation[type](...args) + // #endif + // #ifdef APP-NVUE + this._nvuePushAnimates(type, args) + // #endif + return this + } +}) + +export function createAnimation(option, _this) { + if(!_this) return + clearTimeout(_this.timer) + return new MPAnimation(option, _this) +} diff --git a/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue new file mode 100644 index 00000000..f2bbc72b --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue @@ -0,0 +1,281 @@ + + + + + diff --git a/yanzhu-ui-app/uni_modules/uni-transition/package.json b/yanzhu-ui-app/uni_modules/uni-transition/package.json new file mode 100644 index 00000000..d15fdf01 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-transition/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-transition", + "displayName": "uni-transition 过渡动画", + "version": "1.3.1", + "description": "元素的简单过渡动画", + "keywords": [ + "uni-ui", + "uniui", + "动画", + "过渡", + "过渡动画" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uni_modules/uni-transition/readme.md b/yanzhu-ui-app/uni_modules/uni-transition/readme.md new file mode 100644 index 00000000..2f8a77e1 --- /dev/null +++ b/yanzhu-ui-app/uni_modules/uni-transition/readme.md @@ -0,0 +1,11 @@ + + +## Transition 过渡动画 +> **组件名:uni-transition** +> 代码块: `uTransition` + + +元素过渡动画 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/yanzhu-ui-app/utils/auth.js b/yanzhu-ui-app/utils/auth.js new file mode 100644 index 00000000..659b5493 --- /dev/null +++ b/yanzhu-ui-app/utils/auth.js @@ -0,0 +1,23 @@ +const TokenKey = 'App-Token' + +const OpenIdKey = 'App-OpenId' + +export function getToken() { + return uni.getStorageSync(TokenKey) +} + +export function setToken(token) { + return uni.setStorageSync(TokenKey, token) +} + +export function removeToken() { + return uni.removeStorageSync(TokenKey) +} + +export function getOpenId() { + return uni.getStorageSync(OpenIdKey) +} + +export function setOpenId(openId) { + return uni.setStorageSync(OpenIdKey, openId) +} \ No newline at end of file diff --git a/yanzhu-ui-app/utils/common.js b/yanzhu-ui-app/utils/common.js new file mode 100644 index 00000000..00d4137d --- /dev/null +++ b/yanzhu-ui-app/utils/common.js @@ -0,0 +1,54 @@ +/** +* 显示消息提示框 +* @param content 提示的标题 +*/ +export function toast(content) { + uni.showToast({ + icon: 'none', + title: content + }) +} + +/** +* 显示模态弹窗 +* @param content 提示的标题 +*/ +export function showConfirm(content) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: '提示', + content: content, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + resolve(res) + } + }) + }) +} + +/** +* 参数处理 +* @param params 参数 +*/ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName] + var part = encodeURIComponent(propName) + "=" + if (value !== null && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']' + var subPart = encodeURIComponent(params) + "=" + result += subPart + encodeURIComponent(value[key]) + "&" + } + } + } else { + result += part + encodeURIComponent(value) + "&" + } + } + } + return result +} \ No newline at end of file diff --git a/yanzhu-ui-app/utils/constant.js b/yanzhu-ui-app/utils/constant.js new file mode 100644 index 00000000..f6708641 --- /dev/null +++ b/yanzhu-ui-app/utils/constant.js @@ -0,0 +1,9 @@ +const constant = { + avatar: 'vuex_avatar', + name: 'vuex_name', + roles: 'vuex_roles', + permissions: 'vuex_permissions', + user:'user' + } + + export default constant diff --git a/yanzhu-ui-app/utils/errorCode.js b/yanzhu-ui-app/utils/errorCode.js new file mode 100644 index 00000000..d2111ee1 --- /dev/null +++ b/yanzhu-ui-app/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/yanzhu-ui-app/utils/permission.js b/yanzhu-ui-app/utils/permission.js new file mode 100644 index 00000000..72edc597 --- /dev/null +++ b/yanzhu-ui-app/utils/permission.js @@ -0,0 +1,51 @@ +import store from '@/store' + +/** + * 字符权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkPermi(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = store.getters && store.getters.permissions + const permissionDatas = value + const all_permission = "*:*:*" + + const hasPermission = permissions.some(permission => { + return all_permission === permission || permissionDatas.includes(permission) + }) + + if (!hasPermission) { + return false + } + return true + } else { + //console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) + return false + } +} + +/** + * 角色权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkRole(value) { + if (value && value instanceof Array && value.length > 0) { + const roles = store.getters && store.getters.roles + const permissionRoles = value + const super_admin = "admin" + + const hasRole = roles.some(role => { + return super_admin === role || permissionRoles.includes(role) + }) + + if (!hasRole) { + return false + } + return true + } else { + //console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/utils/request.js b/yanzhu-ui-app/utils/request.js new file mode 100644 index 00000000..cd807700 --- /dev/null +++ b/yanzhu-ui-app/utils/request.js @@ -0,0 +1,87 @@ +import store from '@/store' +import config from '@/config' +import { + getToken +} from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { + toast, + showConfirm, + tansParams +} from '@/utils/common' + +let timeout = 30000 +const baseUrl = config.baseUrl + +const request = config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + config.header = config.header || {} + if (getToken() && !isToken) { + config.header['Authorization'] = 'Bearer ' + getToken() + } + // get请求映射params参数 + if (config.params) { + let url = config.url + '?' + tansParams(config.params) + url = url.slice(0, -1) + config.url = url + } + return new Promise((resolve, reject) => { + uni.showLoading({ + mask: true, + title: '加载中' + }); + uni.request({ + method: config.method || 'get', + timeout: config.timeout || timeout, + url: config.baseUrl || baseUrl + config.url, + data: config.data, + header: config.header, + dataType: 'json' + }).then(response => { + let [error, res] = response + if (error) { + toast('后端接口连接异常') + reject('后端接口连接异常') + return + } + const code = res.data.code || 200 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + if (code === 401) { + showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + if (res.confirm) { + store.dispatch('LogOut').then(res => { + uni.reLaunch({ url: '/pages/login' }) + }) + } + }) + reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + toast(msg) + reject({code:'500',msg:msg}) + } else if (code !== 200) { + toast(msg) + reject(code) + } + resolve(res.data) + uni.hideLoading() + }) + .catch(error => { + let { + message + } = error + if (message === 'Network Error') { + message = '后端接口连接异常' + } else if (message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常' + } + toast(message) + reject(error) + uni.hideLoading() + }) + }) +} + +export default request \ No newline at end of file diff --git a/yanzhu-ui-app/utils/storage.js b/yanzhu-ui-app/utils/storage.js new file mode 100644 index 00000000..2e2557a0 --- /dev/null +++ b/yanzhu-ui-app/utils/storage.js @@ -0,0 +1,32 @@ +import constant from './constant' + +// 存储变量名 +let storageKey = 'storage_data' + +// 存储节点变量名 +let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions,constant.user] + +const storage = { + set: function(key, value) { + if (storageNodeKeys.indexOf(key) != -1) { + let tmp = uni.getStorageSync(storageKey) + tmp = tmp ? tmp : {} + tmp[key] = value + uni.setStorageSync(storageKey, tmp) + } + }, + get: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + return storageData[key] || "" + }, + remove: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + delete storageData[key] + uni.setStorageSync(storageKey, storageData) + }, + clean: function() { + uni.removeStorageSync(storageKey) + } +} + +export default storage diff --git a/yanzhu-ui-app/utils/upload.js b/yanzhu-ui-app/utils/upload.js new file mode 100644 index 00000000..740387e9 --- /dev/null +++ b/yanzhu-ui-app/utils/upload.js @@ -0,0 +1,70 @@ +import store from '@/store' +import config from '@/config' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { toast, showConfirm, tansParams } from '@/utils/common' + +let timeout = 10000 +const baseUrl = config.baseUrl + +const upload = config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + config.header = config.header || {} + if (getToken() && !isToken) { + config.header['Authorization'] = 'Bearer ' + getToken() + } + // get请求映射params参数 + if (config.params) { + let url = config.url + '?' + tansParams(config.params) + url = url.slice(0, -1) + config.url = url + } + return new Promise((resolve, reject) => { + uni.uploadFile({ + timeout: config.timeout || timeout, + url: baseUrl + config.url, + filePath: config.filePath, + name: config.name || 'file', + header: config.header, + formData: config.formData, + success: (res) => { + let result = JSON.parse(res.data) + const code = result.code || 200 + const msg = errorCode[code] || result.msg || errorCode['default'] + if (code === 200) { + resolve(result) + } else if (code == 401) { + showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => { + if (res.confirm) { + store.dispatch('LogOut').then(res => { + uni.reLaunch({ url: '/pages/login/login' }) + }) + } + }) + reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + toast(msg) + reject('500') + } else if (code !== 200) { + toast(msg) + reject(code) + } + }, + fail: (error) => { + let { message } = error + if (message == 'Network Error') { + message = '后端接口连接异常' + } else if (message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常' + } + toast(message) + reject(error) + } + }) + }) +} + +export default upload diff --git a/yanzhu-ui-app/uview-ui/LICENSE b/yanzhu-ui-app/uview-ui/LICENSE new file mode 100644 index 00000000..4db40efe --- /dev/null +++ b/yanzhu-ui-app/uview-ui/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 www.uviewui.com + +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. diff --git a/yanzhu-ui-app/uview-ui/README.md b/yanzhu-ui-app/uview-ui/README.md new file mode 100644 index 00000000..c78ff479 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/README.md @@ -0,0 +1,66 @@ +

+ logo +

+

uView 2.0

+

多平台快速开发的UI框架

+ +[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0) +[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0) +[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues) +[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com) +[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases) +[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License) + +## 说明 + +uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 + +## [官方文档:https://uviewui.com](https://uviewui.com) + + +## 预览 + +您可以通过**微信**扫码,查看最佳的演示效果。 +
+
+ + + +## 链接 + +- [官方文档](https://www.uviewui.com/) +- [更新日志](https://www.uviewui.com/components/changelog.html) +- [升级指南](https://www.uviewui.com/components/changeGuide.html) +- [关于我们](https://www.uviewui.com/cooperation/about.html) + +## 交流反馈 + +欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html) + +## 关于PR + +> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。 +> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢! + +## 安装 + +#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593) + +请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容 + +## 快速上手 + +请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 + +## 使用方法 +配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 + +```html + +``` + +## 版权信息 +uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 + diff --git a/yanzhu-ui-app/uview-ui/changelog.md b/yanzhu-ui-app/uview-ui/changelog.md new file mode 100644 index 00000000..f2bae726 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/changelog.md @@ -0,0 +1,362 @@ +## 2.0.36(2023-03-27) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 重构`deepClone` & `deepMerge`方法 +2. 其他优化 +## 2.0.34(2022-09-24) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. `u-input`、`u-textarea`增加`ignoreCompositionEvent`属性 +2. 修复`route`方法调用可能报错的问题 +3. 修复`u-no-network`组件`z-index`无效的问题 +4. 修复`textarea`组件在h5上confirmType=""报错的问题 +5. `u-rate`适配`nvue` +6. 优化验证手机号码的正则表达式(根据工信部发布的《电信网编号计划(2017年版)》进行修改。) +7. `form-item`添加`labelPosition`属性 +8. `u-calendar`修复`maxDate`设置为当前日期,并且当前时间大于08:00时无法显示日期列表的问题 (#724) +9. `u-radio`增加一个默认插槽用于自定义修改label内容 (#680) +10. 修复`timeFormat`函数在safari重的兼容性问题 (#664) +## 2.0.33(2022-06-17) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复`loadmore`组件`lineColor`类型错误问题 +2. 修复`u-parse`组件`imgtap`、`linktap`不生效问题 +## 2.0.32(2022-06-16) +# uView2.0重磅发布,利剑出鞘,一统江湖 +1. `u-loadmore`新增自定义颜色、虚/实线 +2. 修复`u-swiper-action`组件部分平台不能上下滑动的问题 +3. 修复`u-list`回弹问题 +4. 修复`notice-bar`组件动画在低端安卓机可能会抖动的问题 +5. `u-loading-page`添加控制图标大小的属性`iconSize` +6. 修复`u-tooltip`组件`color`参数不生效的问题 +7. 修复`u--input`组件使用`blur`事件输出为`undefined`的bug +8. `u-code-input`组件新增键盘弹起时,是否自动上推页面参数`adjustPosition` +9. 修复`image`组件`load`事件无回调对象问题 +10. 修复`button`组件`loadingSize`设置无效问题 +10. 其他修复 +## 2.0.31(2022-04-19) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复`upload`在`vue`页面上传成功后没有成功标志的问题 +2. 解决演示项目中微信小程序模拟上传图片一直出于上传中问题 +3. 修复`u-code-input`组件在`nvue`页面编译到`app`平台上光标异常问题(`app`去除此功能) +4. 修复`actionSheet`组件标题关闭按钮点击事件名称错误的问题 +5. 其他修复 +## 2.0.30(2022-04-04) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. `u-rate`增加`readonly`属性 +2. `tabs`滑块支持设置背景图片 +3. 修复`u-subsection` `mode`为`subsection`时,滑块样式不正确的问题 +4. `u-code-input`添加光标效果动画 +5. 修复`popup`的`open`事件不触发 +6. 修复`u-flex-column`无效的问题 +7. 修复`u-datetime-picker`索引在特定场合异常问题 +8. 修复`u-datetime-picker`最小时间字符串模板错误问题 +9. `u-swiper`添加`m3u8`验证 +10. `u-swiper`修改判断image和video逻辑 +11. 修复`swiper`无法使用本地图片问题,增加`type`参数 +12. 修复`u-row-notice`格式错误问题 +13. 修复`u-switch`组件当`unit`为`rpx`时,`nodeStyle`消失的问题 +14. 修复`datetime-picker`组件`showToolbar`与`visibleItemCount`属性无效的问题 +15. 修复`upload`组件条件编译位置判断错误,导致`previewImage`属性设置为`false`时,整个组件都会被隐藏的问题 +16. 修复`u-checkbox-group`设置`shape`属性无效的问题 +17. 修复`u-upload`的`capture`传入字符串的时候不生效的问题 +18. 修复`u-action-sheet`组件,关闭事件逻辑错误的问题 +19. 修复`u-list`触顶事件的触发错误的问题 +20. 修复`u-text`只有手机号可拨打的问题 +21. 修复`u-textarea`不能换行的问题 +22. 其他修复 +## 2.0.29(2022-03-13) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复`u--text`组件设置`decoration`属性未生效的问题 +2. 修复`u-datetime-picker`使用`formatter`后返回值不正确 +3. 修复`u-datetime-picker` `intercept` 可能为undefined +4. 修复已设置单位 uni..config.unit = 'rpx'时,线型指示器 `transform` 的位置翻倍,导致指示器超出宽度 +5. 修复mixin中bem方法生成的类名在支付宝和字节小程序中失效 +6. 修复默认值传值为空的时候,打开`u-datetime-picker`报错,不能选中第一列时间的bug +7. 修复`u-datetime-picker`使用`formatter`后返回值不正确 +8. 修复`u-image`组件`loading`无效果的问题 +9. 修复`config.unit`属性设为`rpx`时,导航栏占用高度不足导致塌陷的问题 +10. 修复`u-datetime-picker`组件`itemHeight`无效问题 +11. 其他修复 +## 2.0.28(2022-02-22) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. search组件新增searchIconSize属性 +2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56 +3. 修复text value.js 判断日期出format错误问题 +4. priceFormat格式化金额出现精度错误 +5. priceFormat在部分情况下出现精度损失问题 +6. 优化表单rules提示 +7. 修复avatar组件src为空时,展示状态不对 +8. 其他修复 +## 2.0.27(2022-01-28) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1.样式修复 +## 2.0.26(2022-01-28) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1.样式修复 +## 2.0.25(2022-01-27) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复text组件mode=price时,可能会导致精度错误的问题 +2. 添加$u.setConfig()方法,可设置uView内置的config, props, zIndex, color属性,详见:[修改uView内置配置方案](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) +3. 优化form组件在errorType=toast时,如果输入错误页面会有抖动的问题 +4. 修复$u.addUnit()对配置默认单位可能无效的问题 +## 2.0.24(2022-01-25) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复swiper在current指定非0时缩放有误 +2. 修复u-icon添加stop属性的时候报错 +3. 优化遗留的通过正则判断rpx单位的问题 +4. 优化Layout布局 vue使用gutter时,会超出固定区域 +5. 优化search组件高度单位问题(rpx -> px) +6. 修复u-image slot 加载和错误的图片失去了高度 +7. 修复u-index-list中footer插槽与header插槽存在性判断错误 +8. 修复部分机型下u-popup关闭时会闪烁 +9. 修复u-image在nvue-app下失去宽高 +10. 修复u-popup运行报错 +11. 修复u-tooltip报错 +12. 修复box-sizing在app下的警告 +13. 修复u-navbar在小程序中报运行时错误 +14. 其他修复 +## 2.0.23(2022-01-24) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复image组件在hx3.3.9的nvue下可能会显示异常的问题 +2. 修复col组件gutter参数带rpx单位处理不正确的问题 +3. 修复text组件单行时无法显示省略号的问题 +4. navbar添加titleStyle参数 +5. 升级到hx3.3.9可消除nvue下控制台样式警告的问题 +## 2.0.22(2022-01-19) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. $u.page()方法优化,避免在特殊场景可能报错的问题 +2. picker组件添加immediateChange参数 +3. 新增$u.pages()方法 +## 2.0.21(2022-01-19) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 优化:form组件在用户设置rules的时候提示用户model必传 +2. 优化遗留的通过正则判断rpx单位的问题 +3. 修复微信小程序环境中tabbar组件开启safeAreaInsetBottom属性后,placeholder高度填充不正确 +4. 修复swiper在current指定非0时缩放有误 +5. 修复u-icon添加stop属性的时候报错 +6. 修复upload组件在accept=all的时候没有作用 +7. 修复在text组件mode为phone时call属性无效的问题 +8. 处理u-form clearValidate方法 +9. 其他修复 +## 2.0.20(2022-01-14) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复calendar默认会选择一个日期,如果直接点确定的话,无法取到值的问题 +2. 修复Slider缺少disabled props 还有注释 +3. 修复u-notice-bar点击事件无法拿到index索引值的问题 +4. 修复u-collapse-item在vue文件下,app端自定义插槽不生效的问题 +5. 优化头像为空时显示默认头像 +6. 修复图片地址赋值后判断加载状态为完成问题 +7. 修复日历滚动到默认日期月份区域 +8. search组件暴露点击左边icon事件 +9. 修复u-form clearValidate方法不生效 +10. upload h5端增加返回文件参数(文件的name参数) +11. 处理upload选择文件后url为blob类型无法预览的问题 +12. u-code-input 修复输入框没有往左移出一半屏幕 +13. 修复Upload上传 disabled为true时,控制台报hoverClass类型错误 +14. 临时处理ios app下grid点击坍塌问题 +15. 其他修复 +## 2.0.19(2021-12-29) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 优化微信小程序包体积可在微信中预览,请升级HbuilderX3.3.4,同时在“运行->运行到小程序模拟器”中勾选“运行时是否压缩代码” +2. 优化微信小程序setData性能,处理某些方法如$u.route()无法在模板中使用的问题 +3. navbar添加autoBack参数 +4. 允许avatar组件的事件冒泡 +5. 修复cell组件报错问题 +6. 其他修复 +## 2.0.18(2021-12-28) +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复app端编译报错问题 +2. 重新处理微信小程序端setData过大的性能问题 +3. 修复边框问题 +4. 修复最大最小月份不大于0则没有数据出现的问题 +5. 修复SwipeAction微信小程序端无法上下滑动问题 +6. 修复input的placeholder在小程序端默认显示为true问题 +7. 修复divider组件click事件无效问题 +8. 修复u-code-input maxlength 属性值为 String 类型时显示异常 +9. 修复当 grid只有 1到2时 在小程序端algin设置无效的问题 +10. 处理form-item的label为top时,取消错误提示的左边距 +11. 其他修复 +## 2.0.17(2021-12-26) +## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 解决HBuilderX3.3.3.20211225版本导致的样式问题 +2. calendar日历添加monthNum参数 +3. navbar添加center slot +## 2.0.16(2021-12-25) +## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 解决微信小程序setData性能问题 +2. 修复count-down组件change事件不触发问题 +## 2.0.15(2021-12-21) +## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复Cell单元格titleWidth无效 +2. 修复cheakbox组件ischecked不更新 +3. 修复keyboard是否显示"."按键默认值问题 +4. 修复number-keyboard是否显示键盘的"."符号问题 +5. 修复Input输入框 readonly无效 +6. 修复u-avatar 导致打包app、H5时候报错问题 +7. 修复Upload上传deletable无效 +8. 修复upload当设置maxSize时无效的问题 +9. 修复tabs lineWidth传入带单位的字符串的时候偏移量计算错误问题 +10. 修复rate组件在有padding的view内,显示的星星位置和可触摸区域不匹配,无法正常选中星星 +## 2.0.13(2021-12-14) +## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复配置默认单位为rpx可能会导致自定义导航栏高度异常的问题 +## 2.0.12(2021-12-14) +## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复tabs组件在vue环境下划线消失的问题 +2. 修复upload组件在安卓小程序无法选择视频的问题 +3. 添加uni.$u.config.unit配置,用于配置参数默认单位,详见:[默认单位配置](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) +4. 修复textarea组件在没绑定v-model时,字符统计不生效问题 +5. 修复nvue下控制是否出现滚动条失效问题 +## 2.0.11(2021-12-13) +## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. text组件align参数无效的问题 +2. subsection组件添加keyName参数 +3. upload组件无法判断[Object file]类型的问题 +4. 处理notify层级过低问题 +5. codeInput组件添加disabledDot参数 +6. 处理actionSheet组件round参数无效的问题 +7. calendar组件添加round参数用于控制圆角值 +8. 处理swipeAction组件在vue环境下默认被打开的问题 +9. button组件的throttleTime节流参数无效的问题 +10. 解决u-notify手动关闭方法close()无效的问题 +11. input组件readonly不生效问题 +12. tag组件type参数为info不生效问题 +## 2.0.10(2021-12-08) +## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复button sendMessagePath属性不生效 +2. 修复DatetimePicker选择器title无效 +3. 修复u-toast设置loading=true不生效 +4. 修复u-text金额模式传0报错 +5. 修复u-toast组件的icon属性配置不生效 +6. button的icon在特殊场景下的颜色优化 +7. IndexList优化,增加# +## 2.0.9(2021-12-01) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 优化swiper的height支持100%值(仅vue有效),修复嵌入视频时click事件无法触发的问题 +2. 优化tabs组件对list值为空的判断,或者动态变化list时重新计算相关尺寸的问题 +3. 优化datetime-picker组件逻辑,让其后续打开的默认值为上一次的选中值,需要通过v-model绑定值才有效 +4. 修复upload内嵌在其他组件中,选择图片可能不会换行的问题 +## 2.0.8(2021-12-01) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复toast的position参数无效问题 +2. 处理input在ios nvue上无法获得焦点的问题 +3. avatar-group组件添加extraValue参数,让剩余展示数量可手动控制 +4. tabs组件添加keyName参数用于配置从对象中读取的键名 +5. 处理text组件名字脱敏默认配置无效的问题 +6. 处理picker组件item文本太长换行问题 +## 2.0.7(2021-11-30) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 修复radio和checkbox动态改变v-model无效的问题。 +2. 优化form规则validator在微信小程序用法 +3. 修复backtop组件mode参数在微信小程序无效的问题 +4. 处理Album的previewFullImage属性无效的问题 +5. 处理u-datetime-picker组件mode='time'在选择改变时间时,控制台报错的问题 +## 2.0.6(2021-11-27) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. 处理tag组件在vue下边框无效的问题。 +2. 处理popup组件圆角参数可能无效的问题。 +3. 处理tabs组件lineColor参数可能无效的问题。 +4. propgress组件在值很小时,显示异常的问题。 +## 2.0.5(2021-11-25) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. calendar在vue下显示异常问题。 +2. form组件labelPosition和errorType参数无效的问题 +3. input组件inputAlign无效的问题 +4. 其他一些修复 +## 2.0.4(2021-11-23) +## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +0. input组件缺失@confirm事件,以及subfix和prefix无效问题 +1. component.scss文件样式在vue下干扰全局布局问题 +2. 修复subsection在vue环境下表现异常的问题 +3. tag组件的bgColor等参数无效的问题 +4. upload组件不换行的问题 +5. 其他的一些修复处理 +## 2.0.3(2021-11-16) +## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. uView2.0已实现全面兼容nvue +2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 +3. 目前uView2.0为公测阶段,相关细节可能会有变动 +4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) +5. 处理modal的confirm回调事件拼写错误问题 +6. 处理input组件@input事件参数错误问题 +7. 其他一些修复 +## 2.0.2(2021-11-16) +## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. uView2.0已实现全面兼容nvue +2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 +3. 目前uView2.0为公测阶段,相关细节可能会有变动 +4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) +5. 修复input组件formatter参数缺失问题 +6. 优化loading-icon组件的scss写法问题,防止不兼容新版本scss +## 2.0.0(2020-11-15) +## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) + +# uView2.0重磅发布,利剑出鞘,一统江湖 + +1. uView2.0已实现全面兼容nvue +2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 +3. 目前uView2.0为公测阶段,相关细节可能会有变动 +4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) +5. 修复input组件formatter参数缺失问题 + + diff --git a/yanzhu-ui-app/uview-ui/components/u--form/u--form.vue b/yanzhu-ui-app/uview-ui/components/u--form/u--form.vue new file mode 100644 index 00000000..fdfc212a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u--form/u--form.vue @@ -0,0 +1,78 @@ + + + diff --git a/yanzhu-ui-app/uview-ui/components/u--image/u--image.vue b/yanzhu-ui-app/uview-ui/components/u--image/u--image.vue new file mode 100644 index 00000000..21b7ab19 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u--image/u--image.vue @@ -0,0 +1,47 @@ + + + \ No newline at end of file diff --git a/yanzhu-ui-app/uview-ui/components/u--input/u--input.vue b/yanzhu-ui-app/uview-ui/components/u--input/u--input.vue new file mode 100644 index 00000000..1e58b010 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u--input/u--input.vue @@ -0,0 +1,73 @@ + + + \ No newline at end of file diff --git a/yanzhu-ui-app/uview-ui/components/u--text/u--text.vue b/yanzhu-ui-app/uview-ui/components/u--text/u--text.vue new file mode 100644 index 00000000..44ee52a3 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u--text/u--text.vue @@ -0,0 +1,44 @@ + + + diff --git a/yanzhu-ui-app/uview-ui/components/u--textarea/u--textarea.vue b/yanzhu-ui-app/uview-ui/components/u--textarea/u--textarea.vue new file mode 100644 index 00000000..f4df0b9a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u--textarea/u--textarea.vue @@ -0,0 +1,48 @@ + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-action-sheet/props.js b/yanzhu-ui-app/uview-ui/components/u-action-sheet/props.js new file mode 100644 index 00000000..e96e04fd --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-action-sheet/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // 操作菜单是否展示 (默认false) + show: { + type: Boolean, + default: uni.$u.props.actionSheet.show + }, + // 标题 + title: { + type: String, + default: uni.$u.props.actionSheet.title + }, + // 选项上方的描述信息 + description: { + type: String, + default: uni.$u.props.actionSheet.description + }, + // 数据 + actions: { + type: Array, + default: uni.$u.props.actionSheet.actions + }, + // 取消按钮的文字,不为空时显示按钮 + cancelText: { + type: String, + default: uni.$u.props.actionSheet.cancelText + }, + // 点击某个菜单项时是否关闭弹窗 + closeOnClickAction: { + type: Boolean, + default: uni.$u.props.actionSheet.closeOnClickAction + }, + // 处理底部安全区(默认true) + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.actionSheet.safeAreaInsetBottom + }, + // 小程序的打开方式 + openType: { + type: String, + default: uni.$u.props.actionSheet.openType + }, + // 点击遮罩是否允许关闭 (默认true) + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.actionSheet.closeOnClickOverlay + }, + // 圆角值 + round: { + type: [Boolean, String, Number], + default: uni.$u.props.actionSheet.round + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-action-sheet/u-action-sheet.vue b/yanzhu-ui-app/uview-ui/components/u-action-sheet/u-action-sheet.vue new file mode 100644 index 00000000..26d5d8d9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-action-sheet/u-action-sheet.vue @@ -0,0 +1,278 @@ + + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-album/props.js b/yanzhu-ui-app/uview-ui/components/u-album/props.js new file mode 100644 index 00000000..75cdb37d --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-album/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // 图片地址,Array|Array形式 + urls: { + type: Array, + default: uni.$u.props.album.urls + }, + // 指定从数组的对象元素中读取哪个属性作为图片地址 + keyName: { + type: String, + default: uni.$u.props.album.keyName + }, + // 单图时,图片长边的长度 + singleSize: { + type: [String, Number], + default: uni.$u.props.album.singleSize + }, + // 多图时,图片边长 + multipleSize: { + type: [String, Number], + default: uni.$u.props.album.multipleSize + }, + // 多图时,图片水平和垂直之间的间隔 + space: { + type: [String, Number], + default: uni.$u.props.album.space + }, + // 单图时,图片缩放裁剪的模式 + singleMode: { + type: String, + default: uni.$u.props.album.singleMode + }, + // 多图时,图片缩放裁剪的模式 + multipleMode: { + type: String, + default: uni.$u.props.album.multipleMode + }, + // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量 + maxCount: { + type: [String, Number], + default: uni.$u.props.album.maxCount + }, + // 是否可以预览图片 + previewFullImage: { + type: Boolean, + default: uni.$u.props.album.previewFullImage + }, + // 每行展示图片数量,如设置,singleSize和multipleSize将会无效 + rowCount: { + type: [String, Number], + default: uni.$u.props.album.rowCount + }, + // 超出maxCount时是否显示查看更多的提示 + showMore: { + type: Boolean, + default: uni.$u.props.album.showMore + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-album/u-album.vue b/yanzhu-ui-app/uview-ui/components/u-album/u-album.vue new file mode 100644 index 00000000..687e2d52 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-album/u-album.vue @@ -0,0 +1,259 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-app/uview-ui/components/u-alert/props.js b/yanzhu-ui-app/uview-ui/components/u-alert/props.js new file mode 100644 index 00000000..4297e2c3 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-alert/props.js @@ -0,0 +1,44 @@ +export default { + props: { + // 显示文字 + title: { + type: String, + default: uni.$u.props.alert.title + }, + // 主题,success/warning/info/error + type: { + type: String, + default: uni.$u.props.alert.type + }, + // 辅助性文字 + description: { + type: String, + default: uni.$u.props.alert.description + }, + // 是否可关闭 + closable: { + type: Boolean, + default: uni.$u.props.alert.closable + }, + // 是否显示图标 + showIcon: { + type: Boolean, + default: uni.$u.props.alert.showIcon + }, + // 浅或深色调,light-浅色,dark-深色 + effect: { + type: String, + default: uni.$u.props.alert.effect + }, + // 文字是否居中 + center: { + type: Boolean, + default: uni.$u.props.alert.center + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.alert.fontSize + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-alert/u-alert.vue b/yanzhu-ui-app/uview-ui/components/u-alert/u-alert.vue new file mode 100644 index 00000000..81f7d43e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-alert/u-alert.vue @@ -0,0 +1,243 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-avatar-group/props.js b/yanzhu-ui-app/uview-ui/components/u-avatar-group/props.js new file mode 100644 index 00000000..58b42ac9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-avatar-group/props.js @@ -0,0 +1,52 @@ +export default { + props: { + // 头像图片组 + urls: { + type: Array, + default: uni.$u.props.avatarGroup.urls + }, + // 最多展示的头像数量 + maxCount: { + type: [String, Number], + default: uni.$u.props.avatarGroup.maxCount + }, + // 头像形状 + shape: { + type: String, + default: uni.$u.props.avatarGroup.shape + }, + // 图片裁剪模式 + mode: { + type: String, + default: uni.$u.props.avatarGroup.mode + }, + // 超出maxCount时是否显示查看更多的提示 + showMore: { + type: Boolean, + default: uni.$u.props.avatarGroup.showMore + }, + // 头像大小 + size: { + type: [String, Number], + default: uni.$u.props.avatarGroup.size + }, + // 指定从数组的对象元素中读取哪个属性作为图片地址 + keyName: { + type: String, + default: uni.$u.props.avatarGroup.keyName + }, + // 头像之间的遮挡比例 + gap: { + type: [String, Number], + validator(value) { + return value >= 0 && value <= 1 + }, + default: uni.$u.props.avatarGroup.gap + }, + // 需额外显示的值 + extraValue: { + type: [Number, String], + default: uni.$u.props.avatarGroup.extraValue + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-avatar-group/u-avatar-group.vue b/yanzhu-ui-app/uview-ui/components/u-avatar-group/u-avatar-group.vue new file mode 100644 index 00000000..7e996d77 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-avatar-group/u-avatar-group.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-avatar/props.js b/yanzhu-ui-app/uview-ui/components/u-avatar/props.js new file mode 100644 index 00000000..34ca0f28 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-avatar/props.js @@ -0,0 +1,78 @@ +export default { + props: { + // 头像图片路径(不能为相对路径) + src: { + type: String, + default: uni.$u.props.avatar.src + }, + // 头像形状,circle-圆形,square-方形 + shape: { + type: String, + default: uni.$u.props.avatar.shape + }, + // 头像尺寸 + size: { + type: [String, Number], + default: uni.$u.props.avatar.size + }, + // 裁剪模式 + mode: { + type: String, + default: uni.$u.props.avatar.mode + }, + // 显示的文字 + text: { + type: String, + default: uni.$u.props.avatar.text + }, + // 背景色 + bgColor: { + type: String, + default: uni.$u.props.avatar.bgColor + }, + // 文字颜色 + color: { + type: String, + default: uni.$u.props.avatar.color + }, + // 文字大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.avatar.fontSize + }, + // 显示的图标 + icon: { + type: String, + default: uni.$u.props.avatar.icon + }, + // 显示小程序头像,只对百度,微信,QQ小程序有效 + mpAvatar: { + type: Boolean, + default: uni.$u.props.avatar.mpAvatar + }, + // 是否使用随机背景色 + randomBgColor: { + type: Boolean, + default: uni.$u.props.avatar.randomBgColor + }, + // 加载失败的默认头像(组件有内置默认图片) + defaultUrl: { + type: String, + default: uni.$u.props.avatar.defaultUrl + }, + // 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间 + colorIndex: { + type: [String, Number], + // 校验参数规则,索引在0-19之间 + validator(n) { + return uni.$u.test.range(n, [0, 19]) || n === '' + }, + default: uni.$u.props.avatar.colorIndex + }, + // 组件标识符 + name: { + type: String, + default: uni.$u.props.avatar.name + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-avatar/u-avatar.vue b/yanzhu-ui-app/uview-ui/components/u-avatar/u-avatar.vue new file mode 100644 index 00000000..3319be58 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-avatar/u-avatar.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-back-top/props.js b/yanzhu-ui-app/uview-ui/components/u-back-top/props.js new file mode 100644 index 00000000..6c702c28 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-back-top/props.js @@ -0,0 +1,54 @@ +export default { + props: { + // 返回顶部的形状,circle-圆形,square-方形 + mode: { + type: String, + default: uni.$u.props.backtop.mode + }, + // 自定义图标 + icon: { + type: String, + default: uni.$u.props.backtop.icon + }, + // 提示文字 + text: { + type: String, + default: uni.$u.props.backtop.text + }, + // 返回顶部滚动时间 + duration: { + type: [String, Number], + default: uni.$u.props.backtop.duration + }, + // 滚动距离 + scrollTop: { + type: [String, Number], + default: uni.$u.props.backtop.scrollTop + }, + // 距离顶部多少距离显示,单位px + top: { + type: [String, Number], + default: uni.$u.props.backtop.top + }, + // 返回顶部按钮到底部的距离,单位px + bottom: { + type: [String, Number], + default: uni.$u.props.backtop.bottom + }, + // 返回顶部按钮到右边的距离,单位px + right: { + type: [String, Number], + default: uni.$u.props.backtop.right + }, + // 层级 + zIndex: { + type: [String, Number], + default: uni.$u.props.backtop.zIndex + }, + // 图标的样式,对象形式 + iconStyle: { + type: Object, + default: uni.$u.props.backtop.iconStyle + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-back-top/u-back-top.vue b/yanzhu-ui-app/uview-ui/components/u-back-top/u-back-top.vue new file mode 100644 index 00000000..2d075667 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-back-top/u-back-top.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-badge/props.js b/yanzhu-ui-app/uview-ui/components/u-badge/props.js new file mode 100644 index 00000000..74c032c3 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-badge/props.js @@ -0,0 +1,72 @@ +export default { + props: { + // 是否显示圆点 + isDot: { + type: Boolean, + default: uni.$u.props.badge.isDot + }, + // 显示的内容 + value: { + type: [Number, String], + default: uni.$u.props.badge.value + }, + // 是否显示 + show: { + type: Boolean, + default: uni.$u.props.badge.show + }, + // 最大值,超过最大值会显示 '{max}+' + max: { + type: [Number, String], + default: uni.$u.props.badge.max + }, + // 主题类型,error|warning|success|primary + type: { + type: String, + default: uni.$u.props.badge.type + }, + // 当数值为 0 时,是否展示 Badge + showZero: { + type: Boolean, + default: uni.$u.props.badge.showZero + }, + // 背景颜色,优先级比type高,如设置,type参数会失效 + bgColor: { + type: [String, null], + default: uni.$u.props.badge.bgColor + }, + // 字体颜色 + color: { + type: [String, null], + default: uni.$u.props.badge.color + }, + // 徽标形状,circle-四角均为圆角,horn-左下角为直角 + shape: { + type: String, + default: uni.$u.props.badge.shape + }, + // 设置数字的显示方式,overflow|ellipsis|limit + // overflow会根据max字段判断,超出显示`${max}+` + // ellipsis会根据max判断,超出显示`${max}...` + // limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数 + numberType: { + type: String, + default: uni.$u.props.badge.numberType + }, + // 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效 + offset: { + type: Array, + default: uni.$u.props.badge.offset + }, + // 是否反转背景和字体颜色 + inverted: { + type: Boolean, + default: uni.$u.props.badge.inverted + }, + // 是否绝对定位 + absolute: { + type: Boolean, + default: uni.$u.props.badge.absolute + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-badge/u-badge.vue b/yanzhu-ui-app/uview-ui/components/u-badge/u-badge.vue new file mode 100644 index 00000000..53cfc811 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-badge/u-badge.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-button/nvue.scss b/yanzhu-ui-app/uview-ui/components/u-button/nvue.scss new file mode 100644 index 00000000..490db7d9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-button/nvue.scss @@ -0,0 +1,46 @@ +$u-button-active-opacity:0.75 !default; +$u-button-loading-text-margin-left:4px !default; +$u-button-text-color: #FFFFFF !default; +$u-button-text-plain-error-color:$u-error !default; +$u-button-text-plain-warning-color:$u-warning !default; +$u-button-text-plain-success-color:$u-success !default; +$u-button-text-plain-info-color:$u-info !default; +$u-button-text-plain-primary-color:$u-primary !default; +.u-button { + &--active { + opacity: $u-button-active-opacity; + } + + &--active--plain { + background-color: rgb(217, 217, 217); + } + + &__loading-text { + margin-left:$u-button-loading-text-margin-left; + } + + &__text, + &__loading-text { + color:$u-button-text-color; + } + + &__text--plain--error { + color:$u-button-text-plain-error-color; + } + + &__text--plain--warning { + color:$u-button-text-plain-warning-color; + } + + &__text--plain--success{ + color:$u-button-text-plain-success-color; + } + + &__text--plain--info { + color:$u-button-text-plain-info-color; + } + + &__text--plain--primary { + color:$u-button-text-plain-primary-color; + } +} \ No newline at end of file diff --git a/yanzhu-ui-app/uview-ui/components/u-button/props.js b/yanzhu-ui-app/uview-ui/components/u-button/props.js new file mode 100644 index 00000000..07fd8446 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-button/props.js @@ -0,0 +1,161 @@ +/* + * @Author : LQ + * @Description : + * @version : 1.0 + * @Date : 2021-08-16 10:04:04 + * @LastAuthor : LQ + * @lastTime : 2021-08-16 10:04:24 + * @FilePath : /u-view2.0/uview-ui/components/u-button/props.js + */ +export default { + props: { + // 是否细边框 + hairline: { + type: Boolean, + default: uni.$u.props.button.hairline + }, + // 按钮的预置样式,info,primary,error,warning,success + type: { + type: String, + default: uni.$u.props.button.type + }, + // 按钮尺寸,large,normal,small,mini + size: { + type: String, + default: uni.$u.props.button.size + }, + // 按钮形状,circle(两边为半圆),square(带圆角) + shape: { + type: String, + default: uni.$u.props.button.shape + }, + // 按钮是否镂空 + plain: { + type: Boolean, + default: uni.$u.props.button.plain + }, + // 是否禁止状态 + disabled: { + type: Boolean, + default: uni.$u.props.button.disabled + }, + // 是否加载中 + loading: { + type: Boolean, + default: uni.$u.props.button.loading + }, + // 加载中提示文字 + loadingText: { + type: [String, Number], + default: uni.$u.props.button.loadingText + }, + // 加载状态图标类型 + loadingMode: { + type: String, + default: uni.$u.props.button.loadingMode + }, + // 加载图标大小 + loadingSize: { + type: [String, Number], + default: uni.$u.props.button.loadingSize + }, + // 开放能力,具体请看uniapp稳定关于button组件部分说明 + // https://uniapp.dcloud.io/component/button + openType: { + type: String, + default: uni.$u.props.button.openType + }, + // 用于 组件,点击分别会触发 组件的 submit/reset 事件 + // 取值为submit(提交表单),reset(重置表单) + formType: { + type: String, + default: uni.$u.props.button.formType + }, + // 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 + // 只微信小程序、QQ小程序有效 + appParameter: { + type: String, + default: uni.$u.props.button.appParameter + }, + // 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效 + hoverStopPropagation: { + type: Boolean, + default: uni.$u.props.button.hoverStopPropagation + }, + // 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效 + lang: { + type: String, + default: uni.$u.props.button.lang + }, + // 会话来源,open-type="contact"时有效。只微信小程序有效 + sessionFrom: { + type: String, + default: uni.$u.props.button.sessionFrom + }, + // 会话内消息卡片标题,open-type="contact"时有效 + // 默认当前标题,只微信小程序有效 + sendMessageTitle: { + type: String, + default: uni.$u.props.button.sendMessageTitle + }, + // 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 + // 默认当前分享路径,只微信小程序有效 + sendMessagePath: { + type: String, + default: uni.$u.props.button.sendMessagePath + }, + // 会话内消息卡片图片,open-type="contact"时有效 + // 默认当前页面截图,只微信小程序有效 + sendMessageImg: { + type: String, + default: uni.$u.props.button.sendMessageImg + }, + // 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示, + // 用户点击后可以快速发送小程序消息,open-type="contact"时有效 + showMessageCard: { + type: Boolean, + default: uni.$u.props.button.showMessageCard + }, + // 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取 + dataName: { + type: String, + default: uni.$u.props.button.dataName + }, + // 节流,一定时间内只能触发一次 + throttleTime: { + type: [String, Number], + default: uni.$u.props.button.throttleTime + }, + // 按住后多久出现点击态,单位毫秒 + hoverStartTime: { + type: [String, Number], + default: uni.$u.props.button.hoverStartTime + }, + // 手指松开后点击态保留时间,单位毫秒 + hoverStayTime: { + type: [String, Number], + default: uni.$u.props.button.hoverStayTime + }, + // 按钮文字,之所以通过props传入,是因为slot传入的话 + // nvue中无法控制文字的样式 + text: { + type: [String, Number], + default: uni.$u.props.button.text + }, + // 按钮图标 + icon: { + type: String, + default: uni.$u.props.button.icon + }, + // 按钮图标 + iconColor: { + type: String, + default: uni.$u.props.button.icon + }, + // 按钮颜色,支持传入linear-gradient渐变色 + color: { + type: String, + default: uni.$u.props.button.color + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-button/u-button.vue b/yanzhu-ui-app/uview-ui/components/u-button/u-button.vue new file mode 100644 index 00000000..5494351e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-button/u-button.vue @@ -0,0 +1,490 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-button/vue.scss b/yanzhu-ui-app/uview-ui/components/u-button/vue.scss new file mode 100644 index 00000000..32019b27 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-button/vue.scss @@ -0,0 +1,80 @@ +// nvue下hover-class无效 +$u-button-before-top:50% !default; +$u-button-before-left:50% !default; +$u-button-before-width:100% !default; +$u-button-before-height:100% !default; +$u-button-before-transform:translate(-50%, -50%) !default; +$u-button-before-opacity:0 !default; +$u-button-before-background-color:#000 !default; +$u-button-before-border-color:#000 !default; +$u-button-active-before-opacity:.15 !default; +$u-button-icon-margin-left:4px !default; +$u-button-plain-u-button-info-color:$u-info; +$u-button-plain-u-button-success-color:$u-success; +$u-button-plain-u-button-error-color:$u-error; +$u-button-plain-u-button-warning-color:$u-error; + +.u-button { + width: 100%; + + &__text { + white-space: nowrap; + line-height: 1; + } + + &:before { + position: absolute; + top:$u-button-before-top; + left:$u-button-before-left; + width:$u-button-before-width; + height:$u-button-before-height; + border: inherit; + border-radius: inherit; + transform:$u-button-before-transform; + opacity:$u-button-before-opacity; + content: " "; + background-color:$u-button-before-background-color; + border-color:$u-button-before-border-color; + } + + &--active { + &:before { + opacity: .15 + } + } + + &__icon+&__text:not(:empty), + &__loading-text { + margin-left:$u-button-icon-margin-left; + } + + &--plain { + &.u-button--primary { + color: $u-primary; + } + } + + &--plain { + &.u-button--info { + color:$u-button-plain-u-button-info-color; + } + } + + &--plain { + &.u-button--success { + color:$u-button-plain-u-button-success-color; + } + } + + &--plain { + &.u-button--error { + color:$u-button-plain-u-button-error-color; + } + } + + &--plain { + &.u-button--warning { + color:$u-button-plain-u-button-warning-color; + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-calendar/header.vue b/yanzhu-ui-app/uview-ui/components/u-calendar/header.vue new file mode 100644 index 00000000..dc4f7d05 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-calendar/header.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-calendar/month.vue b/yanzhu-ui-app/uview-ui/components/u-calendar/month.vue new file mode 100644 index 00000000..c20937fe --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-calendar/month.vue @@ -0,0 +1,579 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-calendar/props.js b/yanzhu-ui-app/uview-ui/components/u-calendar/props.js new file mode 100644 index 00000000..2ad7bc76 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-calendar/props.js @@ -0,0 +1,144 @@ +export default { + props: { + // 日历顶部标题 + title: { + type: String, + default: uni.$u.props.calendar.title + }, + // 是否显示标题 + showTitle: { + type: Boolean, + default: uni.$u.props.calendar.showTitle + }, + // 是否显示副标题 + showSubtitle: { + type: Boolean, + default: uni.$u.props.calendar.showSubtitle + }, + // 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 + mode: { + type: String, + default: uni.$u.props.calendar.mode + }, + // mode=range时,第一个日期底部的提示文字 + startText: { + type: String, + default: uni.$u.props.calendar.startText + }, + // mode=range时,最后一个日期底部的提示文字 + endText: { + type: String, + default: uni.$u.props.calendar.endText + }, + // 自定义列表 + customList: { + type: Array, + default: uni.$u.props.calendar.customList + }, + // 主题色,对底部按钮和选中日期有效 + color: { + type: String, + default: uni.$u.props.calendar.color + }, + // 最小的可选日期 + minDate: { + type: [String, Number], + default: uni.$u.props.calendar.minDate + }, + // 最大可选日期 + maxDate: { + type: [String, Number], + default: uni.$u.props.calendar.maxDate + }, + // 默认选中的日期,mode为multiple或range是必须为数组格式 + defaultDate: { + type: [Array, String, Date, null], + default: uni.$u.props.calendar.defaultDate + }, + // mode=multiple时,最多可选多少个日期 + maxCount: { + type: [String, Number], + default: uni.$u.props.calendar.maxCount + }, + // 日期行高 + rowHeight: { + type: [String, Number], + default: uni.$u.props.calendar.rowHeight + }, + // 日期格式化函数 + formatter: { + type: [Function, null], + default: uni.$u.props.calendar.formatter + }, + // 是否显示农历 + showLunar: { + type: Boolean, + default: uni.$u.props.calendar.showLunar + }, + // 是否显示月份背景色 + showMark: { + type: Boolean, + default: uni.$u.props.calendar.showMark + }, + // 确定按钮的文字 + confirmText: { + type: String, + default: uni.$u.props.calendar.confirmText + }, + // 确认按钮处于禁用状态时的文字 + confirmDisabledText: { + type: String, + default: uni.$u.props.calendar.confirmDisabledText + }, + // 是否显示日历弹窗 + show: { + type: Boolean, + default: uni.$u.props.calendar.show + }, + // 是否允许点击遮罩关闭日历 + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.calendar.closeOnClickOverlay + }, + // 是否为只读状态,只读状态下禁止选择日期 + readonly: { + type: Boolean, + default: uni.$u.props.calendar.readonly + }, + // 是否展示确认按钮 + showConfirm: { + type: Boolean, + default: uni.$u.props.calendar.showConfirm + }, + // 日期区间最多可选天数,默认无限制,mode = range时有效 + maxRange: { + type: [Number, String], + default: uni.$u.props.calendar.maxRange + }, + // 范围选择超过最多可选天数时的提示文案,mode = range时有效 + rangePrompt: { + type: String, + default: uni.$u.props.calendar.rangePrompt + }, + // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 + showRangePrompt: { + type: Boolean, + default: uni.$u.props.calendar.showRangePrompt + }, + // 是否允许日期范围的起止时间为同一天,mode = range时有效 + allowSameDay: { + type: Boolean, + default: uni.$u.props.calendar.allowSameDay + }, + // 圆角值 + round: { + type: [Boolean, String, Number], + default: uni.$u.props.calendar.round + }, + // 最多展示月份数量 + monthNum: { + type: [Number, String], + default: 3 + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-calendar/u-calendar.vue b/yanzhu-ui-app/uview-ui/components/u-calendar/u-calendar.vue new file mode 100644 index 00000000..511f9939 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-calendar/u-calendar.vue @@ -0,0 +1,384 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-calendar/util.js b/yanzhu-ui-app/uview-ui/components/u-calendar/util.js new file mode 100644 index 00000000..ca4736bb --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-calendar/util.js @@ -0,0 +1,85 @@ +export default { + methods: { + // 设置月份数据 + setMonth() { + // 月初是周几 + const day = dayjs(this.date).date(1).day() + const start = day == 0 ? 6 : day - 1 + + // 本月天数 + const days = dayjs(this.date).endOf('month').format('D') + + // 上个月天数 + const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') + + // 日期数据 + const arr = [] + // 清空表格 + this.month = [] + + // 添加上月数据 + arr.push( + ...new Array(start).fill(1).map((e, i) => { + const day = prevDays - start + i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加本月数据 + arr.push( + ...new Array(days - 0).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + date: dayjs(this.date).date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加下个月 + arr.push( + ...new Array(42 - days - start).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 分割数组 + for (let n = 0; n < arr.length; n += 7) { + this.month.push( + arr.slice(n, n + 7).map((e, i) => { + e.index = i + n + + // 自定义信息 + const custom = this.customList.find((c) => c.date == e.date) + + // 农历 + if (this.lunar) { + const { + IDayCn, + IMonthCn + } = this.getLunar(e.date) + e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn + } + + return { + ...e, + ...custom + } + }) + ) + } + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-car-keyboard/props.js b/yanzhu-ui-app/uview-ui/components/u-car-keyboard/props.js new file mode 100644 index 00000000..3553647a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-car-keyboard/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: false + }, + // 输入一个中文后,是否自动切换到英文 + autoChange: { + type: Boolean, + default: false + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/yanzhu-ui-app/uview-ui/components/u-car-keyboard/u-car-keyboard.vue new file mode 100644 index 00000000..51175b54 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-car-keyboard/u-car-keyboard.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-cell-group/props.js b/yanzhu-ui-app/uview-ui/components/u-cell-group/props.js new file mode 100644 index 00000000..350ef403 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-cell-group/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // 分组标题 + title: { + type: String, + default: uni.$u.props.cellGroup.title + }, + // 是否显示外边框 + border: { + type: Boolean, + default: uni.$u.props.cellGroup.border + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-cell-group/u-cell-group.vue b/yanzhu-ui-app/uview-ui/components/u-cell-group/u-cell-group.vue new file mode 100644 index 00000000..a9508c0c --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-cell-group/u-cell-group.vue @@ -0,0 +1,61 @@ + + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-cell/props.js b/yanzhu-ui-app/uview-ui/components/u-cell/props.js new file mode 100644 index 00000000..da033303 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-cell/props.js @@ -0,0 +1,110 @@ +export default { + props: { + // 标题 + title: { + type: [String, Number], + default: uni.$u.props.cell.title + }, + // 标题下方的描述信息 + label: { + type: [String, Number], + default: uni.$u.props.cell.label + }, + // 右侧的内容 + value: { + type: [String, Number], + default: uni.$u.props.cell.value + }, + // 左侧图标名称,或者图片链接(本地文件建议使用绝对地址) + icon: { + type: String, + default: uni.$u.props.cell.icon + }, + // 是否禁用cell + disabled: { + type: Boolean, + default: uni.$u.props.cell.disabled + }, + // 是否显示下边框 + border: { + type: Boolean, + default: uni.$u.props.cell.border + }, + // 内容是否垂直居中(主要是针对右侧的value部分) + center: { + type: Boolean, + default: uni.$u.props.cell.center + }, + // 点击后跳转的URL地址 + url: { + type: String, + default: uni.$u.props.cell.url + }, + // 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 + linkType: { + type: String, + default: uni.$u.props.cell.linkType + }, + // 是否开启点击反馈(表现为点击时加上灰色背景) + clickable: { + type: Boolean, + default: uni.$u.props.cell.clickable + }, + // 是否展示右侧箭头并开启点击反馈 + isLink: { + type: Boolean, + default: uni.$u.props.cell.isLink + }, + // 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) + required: { + type: Boolean, + default: uni.$u.props.cell.required + }, + // 右侧的图标箭头 + rightIcon: { + type: String, + default: uni.$u.props.cell.rightIcon + }, + // 右侧箭头的方向,可选值为:left,up,down + arrowDirection: { + type: String, + default: uni.$u.props.cell.arrowDirection + }, + // 左侧图标样式 + iconStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.iconStyle + } + }, + // 右侧箭头图标的样式 + rightIconStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.rightIconStyle + } + }, + // 标题的样式 + titleStyle: { + type: [Object, String], + default: () => { + return uni.$u.props.cell.titleStyle + } + }, + // 单位元的大小,可选值为large + size: { + type: String, + default: uni.$u.props.cell.size + }, + // 点击cell是否阻止事件传播 + stop: { + type: Boolean, + default: uni.$u.props.cell.stop + }, + // 标识符,cell被点击时返回 + name: { + type: [Number, String], + default: uni.$u.props.cell.name + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-cell/u-cell.vue b/yanzhu-ui-app/uview-ui/components/u-cell/u-cell.vue new file mode 100644 index 00000000..b099c907 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-cell/u-cell.vue @@ -0,0 +1,229 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-checkbox-group/props.js b/yanzhu-ui-app/uview-ui/components/u-checkbox-group/props.js new file mode 100644 index 00000000..2f818a10 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-checkbox-group/props.js @@ -0,0 +1,82 @@ +export default { + props: { + // 标识符 + name: { + type: String, + default: uni.$u.props.checkboxGroup.name + }, + // 绑定的值 + value: { + type: Array, + default: uni.$u.props.checkboxGroup.value + }, + // 形状,circle-圆形,square-方形 + shape: { + type: String, + default: uni.$u.props.checkboxGroup.shape + }, + // 是否禁用全部checkbox + disabled: { + type: Boolean, + default: uni.$u.props.checkboxGroup.disabled + }, + + // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 + activeColor: { + type: String, + default: uni.$u.props.checkboxGroup.activeColor + }, + // 未选中的颜色 + inactiveColor: { + type: String, + default: uni.$u.props.checkboxGroup.inactiveColor + }, + + // 整个组件的尺寸,默认px + size: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.size + }, + // 布局方式,row-横向,column-纵向 + placement: { + type: String, + default: uni.$u.props.checkboxGroup.placement + }, + // label的字体大小,px单位 + labelSize: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.labelSize + }, + // label的字体颜色 + labelColor: { + type: [String], + default: uni.$u.props.checkboxGroup.labelColor + }, + // 是否禁止点击文本操作 + labelDisabled: { + type: Boolean, + default: uni.$u.props.checkboxGroup.labelDisabled + }, + // 图标颜色 + iconColor: { + type: String, + default: uni.$u.props.checkboxGroup.iconColor + }, + // 图标的大小,单位px + iconSize: { + type: [String, Number], + default: uni.$u.props.checkboxGroup.iconSize + }, + // 勾选图标的对齐方式,left-左边,right-右边 + iconPlacement: { + type: String, + default: uni.$u.props.checkboxGroup.iconPlacement + }, + // 竖向配列时,是否显示下划线 + borderBottom: { + type: Boolean, + default: uni.$u.props.checkboxGroup.borderBottom + } + + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/yanzhu-ui-app/uview-ui/components/u-checkbox-group/u-checkbox-group.vue new file mode 100644 index 00000000..7a6b4fa3 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-checkbox-group/u-checkbox-group.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-checkbox/props.js b/yanzhu-ui-app/uview-ui/components/u-checkbox/props.js new file mode 100644 index 00000000..93f4fd9f --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-checkbox/props.js @@ -0,0 +1,69 @@ +export default { + props: { + // checkbox的名称 + name: { + type: [String, Number, Boolean], + default: uni.$u.props.checkbox.name + }, + // 形状,square为方形,circle为圆型 + shape: { + type: String, + default: uni.$u.props.checkbox.shape + }, + // 整体的大小 + size: { + type: [String, Number], + default: uni.$u.props.checkbox.size + }, + // 是否默认选中 + checked: { + type: Boolean, + default: uni.$u.props.checkbox.checked + }, + // 是否禁用 + disabled: { + type: [String, Boolean], + default: uni.$u.props.checkbox.disabled + }, + // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 + activeColor: { + type: String, + default: uni.$u.props.checkbox.activeColor + }, + // 未选中的颜色 + inactiveColor: { + type: String, + default: uni.$u.props.checkbox.inactiveColor + }, + // 图标的大小,单位px + iconSize: { + type: [String, Number], + default: uni.$u.props.checkbox.iconSize + }, + // 图标颜色 + iconColor: { + type: String, + default: uni.$u.props.checkbox.iconColor + }, + // label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 + label: { + type: [String, Number], + default: uni.$u.props.checkbox.label + }, + // label的字体大小,px单位 + labelSize: { + type: [String, Number], + default: uni.$u.props.checkbox.labelSize + }, + // label的颜色 + labelColor: { + type: String, + default: uni.$u.props.checkbox.labelColor + }, + // 是否禁止点击提示语选中复选框 + labelDisabled: { + type: [String, Boolean], + default: uni.$u.props.checkbox.labelDisabled + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-checkbox/u-checkbox.vue b/yanzhu-ui-app/uview-ui/components/u-checkbox/u-checkbox.vue new file mode 100644 index 00000000..6429cca9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-checkbox/u-checkbox.vue @@ -0,0 +1,344 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-circle-progress/props.js b/yanzhu-ui-app/uview-ui/components/u-circle-progress/props.js new file mode 100644 index 00000000..d776cfb6 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-circle-progress/props.js @@ -0,0 +1,8 @@ +export default { + props: { + percentage: { + type: [String, Number], + default: uni.$u.props.circleProgress.percentage + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-circle-progress/u-circle-progress.vue b/yanzhu-ui-app/uview-ui/components/u-circle-progress/u-circle-progress.vue new file mode 100644 index 00000000..d1ee2867 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-circle-progress/u-circle-progress.vue @@ -0,0 +1,198 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-code-input/props.js b/yanzhu-ui-app/uview-ui/components/u-code-input/props.js new file mode 100644 index 00000000..0f016ee0 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-code-input/props.js @@ -0,0 +1,79 @@ +export default { + props: { + // 键盘弹起时,是否自动上推页面 + adjustPosition: { + type: Boolean, + default: uni.$u.props.codeInput.adjustPosition + }, + // 最大输入长度 + maxlength: { + type: [String, Number], + default: uni.$u.props.codeInput.maxlength + }, + // 是否用圆点填充 + dot: { + type: Boolean, + default: uni.$u.props.codeInput.dot + }, + // 显示模式,box-盒子模式,line-底部横线模式 + mode: { + type: String, + default: uni.$u.props.codeInput.mode + }, + // 是否细边框 + hairline: { + type: Boolean, + default: uni.$u.props.codeInput.hairline + }, + // 字符间的距离 + space: { + type: [String, Number], + default: uni.$u.props.codeInput.space + }, + // 预置值 + value: { + type: [String, Number], + default: uni.$u.props.codeInput.value + }, + // 是否自动获取焦点 + focus: { + type: Boolean, + default: uni.$u.props.codeInput.focus + }, + // 字体是否加粗 + bold: { + type: Boolean, + default: uni.$u.props.codeInput.bold + }, + // 字体颜色 + color: { + type: String, + default: uni.$u.props.codeInput.color + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.codeInput.fontSize + }, + // 输入框的大小,宽等于高 + size: { + type: [String, Number], + default: uni.$u.props.codeInput.size + }, + // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true + disabledKeyboard: { + type: Boolean, + default: uni.$u.props.codeInput.disabledKeyboard + }, + // 边框和线条颜色 + borderColor: { + type: String, + default: uni.$u.props.codeInput.borderColor + }, + // 是否禁止输入"."符号 + disabledDot: { + type: Boolean, + default: uni.$u.props.codeInput.disabledDot + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-code-input/u-code-input.vue b/yanzhu-ui-app/uview-ui/components/u-code-input/u-code-input.vue new file mode 100644 index 00000000..96241cfc --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-code-input/u-code-input.vue @@ -0,0 +1,252 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-code/props.js b/yanzhu-ui-app/uview-ui/components/u-code/props.js new file mode 100644 index 00000000..eaf80d02 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-code/props.js @@ -0,0 +1,34 @@ +export default { + props: { + // 倒计时总秒数 + seconds: { + type: [String, Number], + default: uni.$u.props.code.seconds + }, + // 尚未开始时提示 + startText: { + type: String, + default: uni.$u.props.code.startText + }, + // 正在倒计时中的提示 + changeText: { + type: String, + default: uni.$u.props.code.changeText + }, + // 倒计时结束时的提示 + endText: { + type: String, + default: uni.$u.props.code.endText + }, + // 是否在H5刷新或各端返回再进入时继续倒计时 + keepRunning: { + type: Boolean, + default: uni.$u.props.code.keepRunning + }, + // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了 + uniqueKey: { + type: String, + default: uni.$u.props.code.uniqueKey + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-code/u-code.vue b/yanzhu-ui-app/uview-ui/components/u-code/u-code.vue new file mode 100644 index 00000000..f79a09ac --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-code/u-code.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-col/props.js b/yanzhu-ui-app/uview-ui/components/u-col/props.js new file mode 100644 index 00000000..06222517 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-col/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // 占父容器宽度的多少等分,总分为12份 + span: { + type: [String, Number], + default: uni.$u.props.col.span + }, + // 指定栅格左侧的间隔数(总12栏) + offset: { + type: [String, Number], + default: uni.$u.props.col.offset + }, + // 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`) + justify: { + type: String, + default: uni.$u.props.col.justify + }, + // 垂直对齐方式,可选值为top、center、bottom、stretch + align: { + type: String, + default: uni.$u.props.col.align + }, + // 文字对齐方式 + textAlign: { + type: String, + default: uni.$u.props.col.textAlign + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-col/u-col.vue b/yanzhu-ui-app/uview-ui/components/u-col/u-col.vue new file mode 100644 index 00000000..8be15174 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-col/u-col.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-collapse-item/props.js b/yanzhu-ui-app/uview-ui/components/u-collapse-item/props.js new file mode 100644 index 00000000..bd5749b6 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-collapse-item/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // 标题 + title: { + type: String, + default: uni.$u.props.collapseItem.title + }, + // 标题右侧内容 + value: { + type: String, + default: uni.$u.props.collapseItem.value + }, + // 标题下方的描述信息 + label: { + type: String, + default: uni.$u.props.collapseItem.label + }, + // 是否禁用折叠面板 + disabled: { + type: Boolean, + default: uni.$u.props.collapseItem.disabled + }, + // 是否展示右侧箭头并开启点击反馈 + isLink: { + type: Boolean, + default: uni.$u.props.collapseItem.isLink + }, + // 是否开启点击反馈 + clickable: { + type: Boolean, + default: uni.$u.props.collapseItem.clickable + }, + // 是否显示内边框 + border: { + type: Boolean, + default: uni.$u.props.collapseItem.border + }, + // 标题的对齐方式 + align: { + type: String, + default: uni.$u.props.collapseItem.align + }, + // 唯一标识符 + name: { + type: [String, Number], + default: uni.$u.props.collapseItem.name + }, + // 标题左侧图片,可为绝对路径的图片或内置图标 + icon: { + type: String, + default: uni.$u.props.collapseItem.icon + }, + // 面板展开收起的过渡时间,单位ms + duration: { + type: Number, + default: uni.$u.props.collapseItem.duration + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-collapse-item/u-collapse-item.vue b/yanzhu-ui-app/uview-ui/components/u-collapse-item/u-collapse-item.vue new file mode 100644 index 00000000..0e1b7039 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-collapse-item/u-collapse-item.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-collapse/props.js b/yanzhu-ui-app/uview-ui/components/u-collapse/props.js new file mode 100644 index 00000000..7ee6d319 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-collapse/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // 当前展开面板的name,非手风琴模式:[],手风琴模式:string | number + value: { + type: [String, Number, Array, null], + default: uni.$u.props.collapse.value + }, + // 是否手风琴模式 + accordion: { + type: Boolean, + default: uni.$u.props.collapse.accordion + }, + // 是否显示外边框 + border: { + type: Boolean, + default: uni.$u.props.collapse.border + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-collapse/u-collapse.vue b/yanzhu-ui-app/uview-ui/components/u-collapse/u-collapse.vue new file mode 100644 index 00000000..fc188a2e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-collapse/u-collapse.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-column-notice/props.js b/yanzhu-ui-app/uview-ui/components/u-column-notice/props.js new file mode 100644 index 00000000..48091549 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-column-notice/props.js @@ -0,0 +1,55 @@ +export default { + props: { + // 显示的内容,字符串 + text: { + type: [Array], + default: uni.$u.props.columnNotice.text + }, + // 是否显示左侧的音量图标 + icon: { + type: String, + default: uni.$u.props.columnNotice.icon + }, + // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 + mode: { + type: String, + default: uni.$u.props.columnNotice.mode + }, + // 文字颜色,各图标也会使用文字颜色 + color: { + type: String, + default: uni.$u.props.columnNotice.color + }, + // 背景颜色 + bgColor: { + type: String, + default: uni.$u.props.columnNotice.bgColor + }, + // 字体大小,单位px + fontSize: { + type: [String, Number], + default: uni.$u.props.columnNotice.fontSize + }, + // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 + speed: { + type: [String, Number], + default: uni.$u.props.columnNotice.speed + }, + // direction = row时,是否使用步进形式滚动 + step: { + type: Boolean, + default: uni.$u.props.columnNotice.step + }, + // 滚动一个周期的时间长,单位ms + duration: { + type: [String, Number], + default: uni.$u.props.columnNotice.duration + }, + // 是否禁止用手滑动切换 + // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 + disableTouch: { + type: Boolean, + default: uni.$u.props.columnNotice.disableTouch + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-column-notice/u-column-notice.vue b/yanzhu-ui-app/uview-ui/components/u-column-notice/u-column-notice.vue new file mode 100644 index 00000000..fc395321 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-column-notice/u-column-notice.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-count-down/props.js b/yanzhu-ui-app/uview-ui/components/u-count-down/props.js new file mode 100644 index 00000000..d62f0255 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-count-down/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // 倒计时时长,单位ms + time: { + type: [String, Number], + default: uni.$u.props.countDown.time + }, + // 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 + format: { + type: String, + default: uni.$u.props.countDown.format + }, + // 是否自动开始倒计时 + autoStart: { + type: Boolean, + default: uni.$u.props.countDown.autoStart + }, + // 是否展示毫秒倒计时 + millisecond: { + type: Boolean, + default: uni.$u.props.countDown.millisecond + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-count-down/u-count-down.vue b/yanzhu-ui-app/uview-ui/components/u-count-down/u-count-down.vue new file mode 100644 index 00000000..b5e85a63 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-count-down/u-count-down.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-count-down/utils.js b/yanzhu-ui-app/uview-ui/components/u-count-down/utils.js new file mode 100644 index 00000000..8c750050 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-count-down/utils.js @@ -0,0 +1,62 @@ +// 补0,如1 -> 01 +function padZero(num, targetLength = 2) { + let str = `${num}` + while (str.length < targetLength) { + str = `0${str}` + } + return str +} +const SECOND = 1000 +const MINUTE = 60 * SECOND +const HOUR = 60 * MINUTE +const DAY = 24 * HOUR +export function parseTimeData(time) { + const days = Math.floor(time / DAY) + const hours = Math.floor((time % DAY) / HOUR) + const minutes = Math.floor((time % HOUR) / MINUTE) + const seconds = Math.floor((time % MINUTE) / SECOND) + const milliseconds = Math.floor(time % SECOND) + return { + days, + hours, + minutes, + seconds, + milliseconds + } +} +export function parseFormat(format, timeData) { + let { + days, + hours, + minutes, + seconds, + milliseconds + } = timeData + // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去 + if (format.indexOf('DD') === -1) { + hours += days * 24 + } else { + // 对天补0 + format = format.replace('DD', padZero(days)) + } + // 其他同理于DD的格式化处理方式 + if (format.indexOf('HH') === -1) { + minutes += hours * 60 + } else { + format = format.replace('HH', padZero(hours)) + } + if (format.indexOf('mm') === -1) { + seconds += minutes * 60 + } else { + format = format.replace('mm', padZero(minutes)) + } + if (format.indexOf('ss') === -1) { + milliseconds += seconds * 1000 + } else { + format = format.replace('ss', padZero(seconds)) + } + return format.replace('SSS', padZero(milliseconds, 3)) +} +export function isSameSecond(time1, time2) { + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000) +} diff --git a/yanzhu-ui-app/uview-ui/components/u-count-to/props.js b/yanzhu-ui-app/uview-ui/components/u-count-to/props.js new file mode 100644 index 00000000..86873c18 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-count-to/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // 开始的数值,默认从0增长到某一个数 + startVal: { + type: [String, Number], + default: uni.$u.props.countTo.startVal + }, + // 要滚动的目标数值,必须 + endVal: { + type: [String, Number], + default: uni.$u.props.countTo.endVal + }, + // 滚动到目标数值的动画持续时间,单位为毫秒(ms) + duration: { + type: [String, Number], + default: uni.$u.props.countTo.duration + }, + // 设置数值后是否自动开始滚动 + autoplay: { + type: Boolean, + default: uni.$u.props.countTo.autoplay + }, + // 要显示的小数位数 + decimals: { + type: [String, Number], + default: uni.$u.props.countTo.decimals + }, + // 是否在即将到达目标数值的时候,使用缓慢滚动的效果 + useEasing: { + type: Boolean, + default: uni.$u.props.countTo.useEasing + }, + // 十进制分割 + decimal: { + type: [String, Number], + default: uni.$u.props.countTo.decimal + }, + // 字体颜色 + color: { + type: String, + default: uni.$u.props.countTo.color + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.countTo.fontSize + }, + // 是否加粗字体 + bold: { + type: Boolean, + default: uni.$u.props.countTo.bold + }, + // 千位分隔符,类似金额的分割(¥23,321.05中的",") + separator: { + type: String, + default: uni.$u.props.countTo.separator + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-count-to/u-count-to.vue b/yanzhu-ui-app/uview-ui/components/u-count-to/u-count-to.vue new file mode 100644 index 00000000..417b7327 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-count-to/u-count-to.vue @@ -0,0 +1,184 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-datetime-picker/props.js b/yanzhu-ui-app/uview-ui/components/u-datetime-picker/props.js new file mode 100644 index 00000000..f44c0f99 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-datetime-picker/props.js @@ -0,0 +1,116 @@ +export default { + props: { + // 是否打开组件 + show: { + type: Boolean, + default: uni.$u.props.datetimePicker.show + }, + // 是否展示顶部的操作栏 + showToolbar: { + type: Boolean, + default: uni.$u.props.datetimePicker.showToolbar + }, + // 绑定值 + value: { + type: [String, Number], + default: uni.$u.props.datetimePicker.value + }, + // 顶部标题 + title: { + type: String, + default: uni.$u.props.datetimePicker.title + }, + // 展示格式,mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择 + mode: { + type: String, + default: uni.$u.props.datetimePicker.mode + }, + // 可选的最大时间 + maxDate: { + type: Number, + // 最大默认值为后10年 + default: uni.$u.props.datetimePicker.maxDate + }, + // 可选的最小时间 + minDate: { + type: Number, + // 最小默认值为前10年 + default: uni.$u.props.datetimePicker.minDate + }, + // 可选的最小小时,仅mode=time有效 + minHour: { + type: Number, + default: uni.$u.props.datetimePicker.minHour + }, + // 可选的最大小时,仅mode=time有效 + maxHour: { + type: Number, + default: uni.$u.props.datetimePicker.maxHour + }, + // 可选的最小分钟,仅mode=time有效 + minMinute: { + type: Number, + default: uni.$u.props.datetimePicker.minMinute + }, + // 可选的最大分钟,仅mode=time有效 + maxMinute: { + type: Number, + default: uni.$u.props.datetimePicker.maxMinute + }, + // 选项过滤函数 + filter: { + type: [Function, null], + default: uni.$u.props.datetimePicker.filter + }, + // 选项格式化函数 + formatter: { + type: [Function, null], + default: uni.$u.props.datetimePicker.formatter + }, + // 是否显示加载中状态 + loading: { + type: Boolean, + default: uni.$u.props.datetimePicker.loading + }, + // 各列中,单个选项的高度 + itemHeight: { + type: [String, Number], + default: uni.$u.props.datetimePicker.itemHeight + }, + // 取消按钮的文字 + cancelText: { + type: String, + default: uni.$u.props.datetimePicker.cancelText + }, + // 确认按钮的文字 + confirmText: { + type: String, + default: uni.$u.props.datetimePicker.confirmText + }, + // 取消按钮的颜色 + cancelColor: { + type: String, + default: uni.$u.props.datetimePicker.cancelColor + }, + // 确认按钮的颜色 + confirmColor: { + type: String, + default: uni.$u.props.datetimePicker.confirmColor + }, + // 每列中可见选项的数量 + visibleItemCount: { + type: [String, Number], + default: uni.$u.props.datetimePicker.visibleItemCount + }, + // 是否允许点击遮罩关闭选择器 + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.datetimePicker.closeOnClickOverlay + }, + // 各列的默认索引 + defaultIndex: { + type: Array, + default: uni.$u.props.datetimePicker.defaultIndex + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-datetime-picker/u-datetime-picker.vue b/yanzhu-ui-app/uview-ui/components/u-datetime-picker/u-datetime-picker.vue new file mode 100644 index 00000000..18d8dcc6 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-datetime-picker/u-datetime-picker.vue @@ -0,0 +1,360 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-divider/props.js b/yanzhu-ui-app/uview-ui/components/u-divider/props.js new file mode 100644 index 00000000..1fa8359f --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-divider/props.js @@ -0,0 +1,44 @@ +export default { + props: { + // 是否虚线 + dashed: { + type: Boolean, + default: uni.$u.props.divider.dashed + }, + // 是否细线 + hairline: { + type: Boolean, + default: uni.$u.props.divider.hairline + }, + // 是否以点替代文字,优先于text字段起作用 + dot: { + type: Boolean, + default: uni.$u.props.divider.dot + }, + // 内容文本的位置,left-左边,center-中间,right-右边 + textPosition: { + type: String, + default: uni.$u.props.divider.textPosition + }, + // 文本内容 + text: { + type: [String, Number], + default: uni.$u.props.divider.text + }, + // 文本大小 + textSize: { + type: [String, Number], + default: uni.$u.props.divider.textSize + }, + // 文本颜色 + textColor: { + type: String, + default: uni.$u.props.divider.textColor + }, + // 线条颜色 + lineColor: { + type: String, + default: uni.$u.props.divider.lineColor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-divider/u-divider.vue b/yanzhu-ui-app/uview-ui/components/u-divider/u-divider.vue new file mode 100644 index 00000000..b629da64 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-divider/u-divider.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-dropdown-item/props.js b/yanzhu-ui-app/uview-ui/components/u-dropdown-item/props.js new file mode 100644 index 00000000..501a1f05 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-dropdown-item/props.js @@ -0,0 +1,36 @@ +export default { + props: { + // 当前选中项的value值 + value: { + type: [Number, String, Array], + default: '' + }, + // 菜单项标题 + title: { + type: [String, Number], + default: '' + }, + // 选项数据,如果传入了默认slot,此参数无效 + options: { + type: Array, + default() { + return [] + } + }, + // 是否禁用此菜单项 + disabled: { + type: Boolean, + default: false + }, + // 下拉弹窗的高度 + height: { + type: [Number, String], + default: 'auto' + }, + // 点击遮罩是否可以收起弹窗 + closeOnClickOverlay: { + type: Boolean, + default: true + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/yanzhu-ui-app/uview-ui/components/u-dropdown-item/u-dropdown-item.vue new file mode 100644 index 00000000..f830291a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-dropdown-item/u-dropdown-item.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-dropdown/props.js b/yanzhu-ui-app/uview-ui/components/u-dropdown/props.js new file mode 100644 index 00000000..5f8465ef --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-dropdown/props.js @@ -0,0 +1,65 @@ +export default { + props: { + // 标题选中时的样式 + activeStyle: { + type: [String, Object], + default: () => ({ + color: '#2979ff', + fontSize: '14px' + }) + }, + // 标题未选中时的样式 + inactiveStyle: { + type: [String, Object], + default: () => ({ + color: '#606266', + fontSize: '14px' + }) + }, + // 点击遮罩是否关闭菜单 + closeOnClickMask: { + type: Boolean, + default: true + }, + // 点击当前激活项标题是否关闭菜单 + closeOnClickSelf: { + type: Boolean, + default: true + }, + // 过渡时间 + duration: { + type: [Number, String], + default: 300 + }, + // 标题菜单的高度 + height: { + type: [Number, String], + default: 40 + }, + // 是否显示下边框 + borderBottom: { + type: Boolean, + default: false + }, + // 标题的字体大小 + titleSize: { + type: [Number, String], + default: 14 + }, + // 下拉出来的内容部分的圆角值 + borderRadius: { + type: [Number, String], + default: 0 + }, + // 菜单右侧的icon图标 + menuIcon: { + type: String, + default: 'arrow-down' + }, + // 菜单右侧图标的大小 + menuIconSize: { + type: [Number, String], + default: 14 + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-dropdown/u-dropdown.vue b/yanzhu-ui-app/uview-ui/components/u-dropdown/u-dropdown.vue new file mode 100644 index 00000000..f830291a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-dropdown/u-dropdown.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-empty/props.js b/yanzhu-ui-app/uview-ui/components/u-empty/props.js new file mode 100644 index 00000000..78662f8f --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-empty/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // 内置图标名称,或图片路径,建议绝对路径 + icon: { + type: String, + default: uni.$u.props.empty.icon + }, + // 提示文字 + text: { + type: String, + default: uni.$u.props.empty.text + }, + // 文字颜色 + textColor: { + type: String, + default: uni.$u.props.empty.textColor + }, + // 文字大小 + textSize: { + type: [String, Number], + default: uni.$u.props.empty.textSize + }, + // 图标的颜色 + iconColor: { + type: String, + default: uni.$u.props.empty.iconColor + }, + // 图标的大小 + iconSize: { + type: [String, Number], + default: uni.$u.props.empty.iconSize + }, + // 选择预置的图标类型 + mode: { + type: String, + default: uni.$u.props.empty.mode + }, + // 图标宽度,单位px + width: { + type: [String, Number], + default: uni.$u.props.empty.width + }, + // 图标高度,单位px + height: { + type: [String, Number], + default: uni.$u.props.empty.height + }, + // 是否显示组件 + show: { + type: Boolean, + default: uni.$u.props.empty.show + }, + // 组件距离上一个元素之间的距离,默认px单位 + marginTop: { + type: [String, Number], + default: uni.$u.props.empty.marginTop + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-empty/u-empty.vue b/yanzhu-ui-app/uview-ui/components/u-empty/u-empty.vue new file mode 100644 index 00000000..03d6a273 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-empty/u-empty.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-form-item/props.js b/yanzhu-ui-app/uview-ui/components/u-form-item/props.js new file mode 100644 index 00000000..7b166556 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-form-item/props.js @@ -0,0 +1,48 @@ +export default { + props: { + // input的label提示语 + label: { + type: String, + default: uni.$u.props.formItem.label + }, + // 绑定的值 + prop: { + type: String, + default: uni.$u.props.formItem.prop + }, + // 是否显示表单域的下划线边框 + borderBottom: { + type: [String, Boolean], + default: uni.$u.props.formItem.borderBottom + }, + // label的位置,left-左边,top-上边 + labelPosition: { + type: String, + default: uni.$u.props.formItem.labelPosition + }, + // label的宽度,单位px + labelWidth: { + type: [String, Number], + default: uni.$u.props.formItem.labelWidth + }, + // 右侧图标 + rightIcon: { + type: String, + default: uni.$u.props.formItem.rightIcon + }, + // 左侧图标 + leftIcon: { + type: String, + default: uni.$u.props.formItem.leftIcon + }, + // 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置 + required: { + type: Boolean, + default: uni.$u.props.formItem.required + }, + leftIconStyle: { + type: [String, Object], + default: uni.$u.props.formItem.leftIconStyle, + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-form-item/u-form-item.vue b/yanzhu-ui-app/uview-ui/components/u-form-item/u-form-item.vue new file mode 100644 index 00000000..6aa8d690 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-form-item/u-form-item.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-form/props.js b/yanzhu-ui-app/uview-ui/components/u-form/props.js new file mode 100644 index 00000000..f2a629c0 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-form/props.js @@ -0,0 +1,45 @@ +export default { + props: { + // 当前form的需要验证字段的集合 + model: { + type: Object, + default: uni.$u.props.form.model + }, + // 验证规则 + rules: { + type: [Object, Function, Array], + default: uni.$u.props.form.rules + }, + // 有错误时的提示方式,message-提示信息,toast-进行toast提示 + // border-bottom-下边框呈现红色,none-无提示 + errorType: { + type: String, + default: uni.$u.props.form.errorType + }, + // 是否显示表单域的下划线边框 + borderBottom: { + type: Boolean, + default: uni.$u.props.form.borderBottom + }, + // label的位置,left-左边,top-上边 + labelPosition: { + type: String, + default: uni.$u.props.form.labelPosition + }, + // label的宽度,单位px + labelWidth: { + type: [String, Number], + default: uni.$u.props.form.labelWidth + }, + // lable字体的对齐方式 + labelAlign: { + type: String, + default: uni.$u.props.form.labelAlign + }, + // lable的样式,对象形式 + labelStyle: { + type: Object, + default: uni.$u.props.form.labelStyle + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-form/u-form.vue b/yanzhu-ui-app/uview-ui/components/u-form/u-form.vue new file mode 100644 index 00000000..fe2dde2d --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-form/u-form.vue @@ -0,0 +1,214 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-gap/props.js b/yanzhu-ui-app/uview-ui/components/u-gap/props.js new file mode 100644 index 00000000..89953e32 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-gap/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // 背景颜色(默认transparent) + bgColor: { + type: String, + default: uni.$u.props.gap.bgColor + }, + // 分割槽高度,单位px(默认30) + height: { + type: [String, Number], + default: uni.$u.props.gap.height + }, + // 与上一个组件的距离 + marginTop: { + type: [String, Number], + default: uni.$u.props.gap.marginTop + }, + // 与下一个组件的距离 + marginBottom: { + type: [String, Number], + default: uni.$u.props.gap.marginBottom + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-gap/u-gap.vue b/yanzhu-ui-app/uview-ui/components/u-gap/u-gap.vue new file mode 100644 index 00000000..e4429f0e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-gap/u-gap.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-grid-item/props.js b/yanzhu-ui-app/uview-ui/components/u-grid-item/props.js new file mode 100644 index 00000000..06c3c663 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-grid-item/props.js @@ -0,0 +1,14 @@ +export default { + props: { + // 宫格的name + name: { + type: [String, Number, null], + default: uni.$u.props.gridItem.name + }, + // 背景颜色 + bgColor: { + type: String, + default: uni.$u.props.gridItem.bgColor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-grid-item/u-grid-item.vue b/yanzhu-ui-app/uview-ui/components/u-grid-item/u-grid-item.vue new file mode 100644 index 00000000..fc0c7cf1 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-grid-item/u-grid-item.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-grid/props.js b/yanzhu-ui-app/uview-ui/components/u-grid/props.js new file mode 100644 index 00000000..87b0f6a7 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-grid/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // 分成几列 + col: { + type: [String, Number], + default: uni.$u.props.grid.col + }, + // 是否显示边框 + border: { + type: Boolean, + default: uni.$u.props.grid.border + }, + // 宫格对齐方式,表现为数量少的时候,靠左,居中,还是靠右 + align: { + type: String, + default: uni.$u.props.grid.align + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-grid/u-grid.vue b/yanzhu-ui-app/uview-ui/components/u-grid/u-grid.vue new file mode 100644 index 00000000..b43cc270 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-grid/u-grid.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-icon/icons.js b/yanzhu-ui-app/uview-ui/components/u-icon/icons.js new file mode 100644 index 00000000..f4d0fe29 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-icon/icons.js @@ -0,0 +1,214 @@ +export default { + 'uicon-level': '\ue693', + 'uicon-column-line': '\ue68e', + 'uicon-checkbox-mark': '\ue807', + 'uicon-folder': '\ue7f5', + 'uicon-movie': '\ue7f6', + 'uicon-star-fill': '\ue669', + 'uicon-star': '\ue65f', + 'uicon-phone-fill': '\ue64f', + 'uicon-phone': '\ue622', + 'uicon-apple-fill': '\ue881', + 'uicon-chrome-circle-fill': '\ue885', + 'uicon-backspace': '\ue67b', + 'uicon-attach': '\ue632', + 'uicon-cut': '\ue948', + 'uicon-empty-car': '\ue602', + 'uicon-empty-coupon': '\ue682', + 'uicon-empty-address': '\ue646', + 'uicon-empty-favor': '\ue67c', + 'uicon-empty-permission': '\ue686', + 'uicon-empty-news': '\ue687', + 'uicon-empty-search': '\ue664', + 'uicon-github-circle-fill': '\ue887', + 'uicon-rmb': '\ue608', + 'uicon-person-delete-fill': '\ue66a', + 'uicon-reload': '\ue788', + 'uicon-order': '\ue68f', + 'uicon-server-man': '\ue6bc', + 'uicon-search': '\ue62a', + 'uicon-fingerprint': '\ue955', + 'uicon-more-dot-fill': '\ue630', + 'uicon-scan': '\ue662', + 'uicon-share-square': '\ue60b', + 'uicon-map': '\ue61d', + 'uicon-map-fill': '\ue64e', + 'uicon-tags': '\ue629', + 'uicon-tags-fill': '\ue651', + 'uicon-bookmark-fill': '\ue63b', + 'uicon-bookmark': '\ue60a', + 'uicon-eye': '\ue613', + 'uicon-eye-fill': '\ue641', + 'uicon-mic': '\ue64a', + 'uicon-mic-off': '\ue649', + 'uicon-calendar': '\ue66e', + 'uicon-calendar-fill': '\ue634', + 'uicon-trash': '\ue623', + 'uicon-trash-fill': '\ue658', + 'uicon-play-left': '\ue66d', + 'uicon-play-right': '\ue610', + 'uicon-minus': '\ue618', + 'uicon-plus': '\ue62d', + 'uicon-info': '\ue653', + 'uicon-info-circle': '\ue7d2', + 'uicon-info-circle-fill': '\ue64b', + 'uicon-question': '\ue715', + 'uicon-error': '\ue6d3', + 'uicon-close': '\ue685', + 'uicon-checkmark': '\ue6a8', + 'uicon-android-circle-fill': '\ue67e', + 'uicon-android-fill': '\ue67d', + 'uicon-ie': '\ue87b', + 'uicon-IE-circle-fill': '\ue889', + 'uicon-google': '\ue87a', + 'uicon-google-circle-fill': '\ue88a', + 'uicon-setting-fill': '\ue872', + 'uicon-setting': '\ue61f', + 'uicon-minus-square-fill': '\ue855', + 'uicon-plus-square-fill': '\ue856', + 'uicon-heart': '\ue7df', + 'uicon-heart-fill': '\ue851', + 'uicon-camera': '\ue7d7', + 'uicon-camera-fill': '\ue870', + 'uicon-more-circle': '\ue63e', + 'uicon-more-circle-fill': '\ue645', + 'uicon-chat': '\ue620', + 'uicon-chat-fill': '\ue61e', + 'uicon-bag-fill': '\ue617', + 'uicon-bag': '\ue619', + 'uicon-error-circle-fill': '\ue62c', + 'uicon-error-circle': '\ue624', + 'uicon-close-circle': '\ue63f', + 'uicon-close-circle-fill': '\ue637', + 'uicon-checkmark-circle': '\ue63d', + 'uicon-checkmark-circle-fill': '\ue635', + 'uicon-question-circle-fill': '\ue666', + 'uicon-question-circle': '\ue625', + 'uicon-share': '\ue631', + 'uicon-share-fill': '\ue65e', + 'uicon-shopping-cart': '\ue621', + 'uicon-shopping-cart-fill': '\ue65d', + 'uicon-bell': '\ue609', + 'uicon-bell-fill': '\ue640', + 'uicon-list': '\ue650', + 'uicon-list-dot': '\ue616', + 'uicon-zhihu': '\ue6ba', + 'uicon-zhihu-circle-fill': '\ue709', + 'uicon-zhifubao': '\ue6b9', + 'uicon-zhifubao-circle-fill': '\ue6b8', + 'uicon-weixin-circle-fill': '\ue6b1', + 'uicon-weixin-fill': '\ue6b2', + 'uicon-twitter-circle-fill': '\ue6ab', + 'uicon-twitter': '\ue6aa', + 'uicon-taobao-circle-fill': '\ue6a7', + 'uicon-taobao': '\ue6a6', + 'uicon-weibo-circle-fill': '\ue6a5', + 'uicon-weibo': '\ue6a4', + 'uicon-qq-fill': '\ue6a1', + 'uicon-qq-circle-fill': '\ue6a0', + 'uicon-moments-circel-fill': '\ue69a', + 'uicon-moments': '\ue69b', + 'uicon-qzone': '\ue695', + 'uicon-qzone-circle-fill': '\ue696', + 'uicon-baidu-circle-fill': '\ue680', + 'uicon-baidu': '\ue681', + 'uicon-facebook-circle-fill': '\ue68a', + 'uicon-facebook': '\ue689', + 'uicon-car': '\ue60c', + 'uicon-car-fill': '\ue636', + 'uicon-warning-fill': '\ue64d', + 'uicon-warning': '\ue694', + 'uicon-clock-fill': '\ue638', + 'uicon-clock': '\ue60f', + 'uicon-edit-pen': '\ue612', + 'uicon-edit-pen-fill': '\ue66b', + 'uicon-email': '\ue611', + 'uicon-email-fill': '\ue642', + 'uicon-minus-circle': '\ue61b', + 'uicon-minus-circle-fill': '\ue652', + 'uicon-plus-circle': '\ue62e', + 'uicon-plus-circle-fill': '\ue661', + 'uicon-file-text': '\ue663', + 'uicon-file-text-fill': '\ue665', + 'uicon-pushpin': '\ue7e3', + 'uicon-pushpin-fill': '\ue86e', + 'uicon-grid': '\ue673', + 'uicon-grid-fill': '\ue678', + 'uicon-play-circle': '\ue647', + 'uicon-play-circle-fill': '\ue655', + 'uicon-pause-circle-fill': '\ue654', + 'uicon-pause': '\ue8fa', + 'uicon-pause-circle': '\ue643', + 'uicon-eye-off': '\ue648', + 'uicon-eye-off-outline': '\ue62b', + 'uicon-gift-fill': '\ue65c', + 'uicon-gift': '\ue65b', + 'uicon-rmb-circle-fill': '\ue657', + 'uicon-rmb-circle': '\ue677', + 'uicon-kefu-ermai': '\ue656', + 'uicon-server-fill': '\ue751', + 'uicon-coupon-fill': '\ue8c4', + 'uicon-coupon': '\ue8ae', + 'uicon-integral': '\ue704', + 'uicon-integral-fill': '\ue703', + 'uicon-home-fill': '\ue964', + 'uicon-home': '\ue965', + 'uicon-hourglass-half-fill': '\ue966', + 'uicon-hourglass': '\ue967', + 'uicon-account': '\ue628', + 'uicon-plus-people-fill': '\ue626', + 'uicon-minus-people-fill': '\ue615', + 'uicon-account-fill': '\ue614', + 'uicon-thumb-down-fill': '\ue726', + 'uicon-thumb-down': '\ue727', + 'uicon-thumb-up': '\ue733', + 'uicon-thumb-up-fill': '\ue72f', + 'uicon-lock-fill': '\ue979', + 'uicon-lock-open': '\ue973', + 'uicon-lock-opened-fill': '\ue974', + 'uicon-lock': '\ue97a', + 'uicon-red-packet-fill': '\ue690', + 'uicon-photo-fill': '\ue98b', + 'uicon-photo': '\ue98d', + 'uicon-volume-off-fill': '\ue659', + 'uicon-volume-off': '\ue644', + 'uicon-volume-fill': '\ue670', + 'uicon-volume': '\ue633', + 'uicon-red-packet': '\ue691', + 'uicon-download': '\ue63c', + 'uicon-arrow-up-fill': '\ue6b0', + 'uicon-arrow-down-fill': '\ue600', + 'uicon-play-left-fill': '\ue675', + 'uicon-play-right-fill': '\ue676', + 'uicon-rewind-left-fill': '\ue679', + 'uicon-rewind-right-fill': '\ue67a', + 'uicon-arrow-downward': '\ue604', + 'uicon-arrow-leftward': '\ue601', + 'uicon-arrow-rightward': '\ue603', + 'uicon-arrow-upward': '\ue607', + 'uicon-arrow-down': '\ue60d', + 'uicon-arrow-right': '\ue605', + 'uicon-arrow-left': '\ue60e', + 'uicon-arrow-up': '\ue606', + 'uicon-skip-back-left': '\ue674', + 'uicon-skip-forward-right': '\ue672', + 'uicon-rewind-right': '\ue66f', + 'uicon-rewind-left': '\ue671', + 'uicon-arrow-right-double': '\ue68d', + 'uicon-arrow-left-double': '\ue68c', + 'uicon-wifi-off': '\ue668', + 'uicon-wifi': '\ue667', + 'uicon-empty-data': '\ue62f', + 'uicon-empty-history': '\ue684', + 'uicon-empty-list': '\ue68b', + 'uicon-empty-page': '\ue627', + 'uicon-empty-order': '\ue639', + 'uicon-man': '\ue697', + 'uicon-woman': '\ue69c', + 'uicon-man-add': '\ue61c', + 'uicon-man-add-fill': '\ue64c', + 'uicon-man-delete': '\ue61a', + 'uicon-man-delete-fill': '\ue66a', + 'uicon-zh': '\ue70a', + 'uicon-en': '\ue692' +} diff --git a/yanzhu-ui-app/uview-ui/components/u-icon/props.js b/yanzhu-ui-app/uview-ui/components/u-icon/props.js new file mode 100644 index 00000000..71845b7c --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-icon/props.js @@ -0,0 +1,89 @@ +export default { + props: { + // 图标类名 + name: { + type: String, + default: uni.$u.props.icon.name + }, + // 图标颜色,可接受主题色 + color: { + type: String, + default: uni.$u.props.icon.color + }, + // 字体大小,单位px + size: { + type: [String, Number], + default: uni.$u.props.icon.size + }, + // 是否显示粗体 + bold: { + type: Boolean, + default: uni.$u.props.icon.bold + }, + // 点击图标的时候传递事件出去的index(用于区分点击了哪一个) + index: { + type: [String, Number], + default: uni.$u.props.icon.index + }, + // 触摸图标时的类名 + hoverClass: { + type: String, + default: uni.$u.props.icon.hoverClass + }, + // 自定义扩展前缀,方便用户扩展自己的图标库 + customPrefix: { + type: String, + default: uni.$u.props.icon.customPrefix + }, + // 图标右边或者下面的文字 + label: { + type: [String, Number], + default: uni.$u.props.icon.label + }, + // label的位置,只能右边或者下边 + labelPos: { + type: String, + default: uni.$u.props.icon.labelPos + }, + // label的大小 + labelSize: { + type: [String, Number], + default: uni.$u.props.icon.labelSize + }, + // label的颜色 + labelColor: { + type: String, + default: uni.$u.props.icon.labelColor + }, + // label与图标的距离 + space: { + type: [String, Number], + default: uni.$u.props.icon.space + }, + // 图片的mode + imgMode: { + type: String, + default: uni.$u.props.icon.imgMode + }, + // 用于显示图片小图标时,图片的宽度 + width: { + type: [String, Number], + default: uni.$u.props.icon.width + }, + // 用于显示图片小图标时,图片的高度 + height: { + type: [String, Number], + default: uni.$u.props.icon.height + }, + // 用于解决某些情况下,让图标垂直居中的用途 + top: { + type: [String, Number], + default: uni.$u.props.icon.top + }, + // 是否阻止事件传播 + stop: { + type: Boolean, + default: uni.$u.props.icon.stop + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-icon/u-icon.vue b/yanzhu-ui-app/uview-ui/components/u-icon/u-icon.vue new file mode 100644 index 00000000..9340328e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-icon/u-icon.vue @@ -0,0 +1,234 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-image/props.js b/yanzhu-ui-app/uview-ui/components/u-image/props.js new file mode 100644 index 00000000..2eabb746 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-image/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // 图片地址 + src: { + type: String, + default: uni.$u.props.image.src + }, + // 裁剪模式 + mode: { + type: String, + default: uni.$u.props.image.mode + }, + // 宽度,单位任意 + width: { + type: [String, Number], + default: uni.$u.props.image.width + }, + // 高度,单位任意 + height: { + type: [String, Number], + default: uni.$u.props.image.height + }, + // 图片形状,circle-圆形,square-方形 + shape: { + type: String, + default: uni.$u.props.image.shape + }, + // 圆角,单位任意 + radius: { + type: [String, Number], + default: uni.$u.props.image.radius + }, + // 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序 + lazyLoad: { + type: Boolean, + default: uni.$u.props.image.lazyLoad + }, + // 开启长按图片显示识别微信小程序码菜单 + showMenuByLongpress: { + type: Boolean, + default: uni.$u.props.image.showMenuByLongpress + }, + // 加载中的图标,或者小图片 + loadingIcon: { + type: String, + default: uni.$u.props.image.loadingIcon + }, + // 加载失败的图标,或者小图片 + errorIcon: { + type: String, + default: uni.$u.props.image.errorIcon + }, + // 是否显示加载中的图标或者自定义的slot + showLoading: { + type: Boolean, + default: uni.$u.props.image.showLoading + }, + // 是否显示加载错误的图标或者自定义的slot + showError: { + type: Boolean, + default: uni.$u.props.image.showError + }, + // 是否需要淡入效果 + fade: { + type: Boolean, + default: uni.$u.props.image.fade + }, + // 只支持网络资源,只对微信小程序有效 + webp: { + type: Boolean, + default: uni.$u.props.image.webp + }, + // 过渡时间,单位ms + duration: { + type: [String, Number], + default: uni.$u.props.image.duration + }, + // 背景颜色,用于深色页面加载图片时,为了和背景色融合 + bgColor: { + type: String, + default: uni.$u.props.image.bgColor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-image/u-image.vue b/yanzhu-ui-app/uview-ui/components/u-image/u-image.vue new file mode 100644 index 00000000..473e35b4 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-image/u-image.vue @@ -0,0 +1,232 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-index-anchor/props.js b/yanzhu-ui-app/uview-ui/components/u-index-anchor/props.js new file mode 100644 index 00000000..6d8b59a7 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-anchor/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // 列表锚点文本内容 + text: { + type: [String, Number], + default: uni.$u.props.indexAnchor.text + }, + // 列表锚点文字颜色 + color: { + type: String, + default: uni.$u.props.indexAnchor.color + }, + // 列表锚点文字大小,单位默认px + size: { + type: [String, Number], + default: uni.$u.props.indexAnchor.size + }, + // 列表锚点背景颜色 + bgColor: { + type: String, + default: uni.$u.props.indexAnchor.bgColor + }, + // 列表锚点高度,单位默认px + height: { + type: [String, Number], + default: uni.$u.props.indexAnchor.height + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-index-anchor/u-index-anchor.vue b/yanzhu-ui-app/uview-ui/components/u-index-anchor/u-index-anchor.vue new file mode 100644 index 00000000..b95ddef9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-anchor/u-index-anchor.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-index-item/props.js b/yanzhu-ui-app/uview-ui/components/u-index-item/props.js new file mode 100644 index 00000000..7c113311 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-item/props.js @@ -0,0 +1,5 @@ +export default { + props: { + + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-index-item/u-index-item.vue b/yanzhu-ui-app/uview-ui/components/u-index-item/u-index-item.vue new file mode 100644 index 00000000..0bc7fb3c --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-item/u-index-item.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-index-list/props.js b/yanzhu-ui-app/uview-ui/components/u-index-list/props.js new file mode 100644 index 00000000..354d4591 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-list/props.js @@ -0,0 +1,29 @@ +export default { + props: { + // 右边锚点非激活的颜色 + inactiveColor: { + type: String, + default: uni.$u.props.indexList.inactiveColor + }, + // 右边锚点激活的颜色 + activeColor: { + type: String, + default: uni.$u.props.indexList.activeColor + }, + // 索引字符列表,数组形式 + indexList: { + type: Array, + default: uni.$u.props.indexList.indexList + }, + // 是否开启锚点自动吸顶 + sticky: { + type: Boolean, + default: uni.$u.props.indexList.sticky + }, + // 自定义导航栏的高度 + customNavHeight: { + type: [String, Number], + default: uni.$u.props.indexList.customNavHeight + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-index-list/u-index-list.vue b/yanzhu-ui-app/uview-ui/components/u-index-list/u-index-list.vue new file mode 100644 index 00000000..d7126185 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-index-list/u-index-list.vue @@ -0,0 +1,440 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-input/props.js b/yanzhu-ui-app/uview-ui/components/u-input/props.js new file mode 100644 index 00000000..2c508701 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-input/props.js @@ -0,0 +1,187 @@ +export default { + props: { + // 输入的值 + value: { + type: [String, Number], + default: uni.$u.props.input.value + }, + // 输入框类型 + // number-数字输入键盘,app-vue下可以输入浮点数,app-nvue和小程序平台下只能输入整数 + // idcard-身份证输入键盘,微信、支付宝、百度、QQ小程序 + // digit-带小数点的数字键盘,App的nvue页面、微信、支付宝、百度、头条、QQ小程序 + // text-文本输入键盘 + type: { + type: String, + default: uni.$u.props.input.type + }, + // 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true, + // 兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序 + fixed: { + type: Boolean, + default: uni.$u.props.input.fixed + }, + // 是否禁用输入框 + disabled: { + type: Boolean, + default: uni.$u.props.input.disabled + }, + // 禁用状态时的背景色 + disabledColor: { + type: String, + default: uni.$u.props.input.disabledColor + }, + // 是否显示清除控件 + clearable: { + type: Boolean, + default: uni.$u.props.input.clearable + }, + // 是否密码类型 + password: { + type: Boolean, + default: uni.$u.props.input.password + }, + // 最大输入长度,设置为 -1 的时候不限制最大长度 + maxlength: { + type: [String, Number], + default: uni.$u.props.input.maxlength + }, + // 输入框为空时的占位符 + placeholder: { + type: String, + default: uni.$u.props.input.placeholder + }, + // 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/ + placeholderClass: { + type: String, + default: uni.$u.props.input.placeholderClass + }, + // 指定placeholder的样式 + placeholderStyle: { + type: [String, Object], + default: uni.$u.props.input.placeholderStyle + }, + // 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效 + showWordLimit: { + type: Boolean, + default: uni.$u.props.input.showWordLimit + }, + // 设置右下角按钮的文字,有效值:send|search|next|go|done,兼容性详见uni-app文档 + // https://uniapp.dcloud.io/component/input + // https://uniapp.dcloud.io/component/textarea + confirmType: { + type: String, + default: uni.$u.props.input.confirmType + }, + // 点击键盘右下角按钮时是否保持键盘不收起,H5无效 + confirmHold: { + type: Boolean, + default: uni.$u.props.input.confirmHold + }, + // focus时,点击页面的时候不收起键盘,微信小程序有效 + holdKeyboard: { + type: Boolean, + default: uni.$u.props.input.holdKeyboard + }, + // 自动获取焦点 + // 在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点 + focus: { + type: Boolean, + default: uni.$u.props.input.focus + }, + // 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效 + autoBlur: { + type: Boolean, + default: uni.$u.props.input.autoBlur + }, + // 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效 + disableDefaultPadding: { + type: Boolean, + default: uni.$u.props.input.disableDefaultPadding + }, + // 指定focus时光标的位置 + cursor: { + type: [String, Number], + default: uni.$u.props.input.cursor + }, + // 输入框聚焦时底部与键盘的距离 + cursorSpacing: { + type: [String, Number], + default: uni.$u.props.input.cursorSpacing + }, + // 光标起始位置,自动聚集时有效,需与selection-end搭配使用 + selectionStart: { + type: [String, Number], + default: uni.$u.props.input.selectionStart + }, + // 光标结束位置,自动聚集时有效,需与selection-start搭配使用 + selectionEnd: { + type: [String, Number], + default: uni.$u.props.input.selectionEnd + }, + // 键盘弹起时,是否自动上推页面 + adjustPosition: { + type: Boolean, + default: uni.$u.props.input.adjustPosition + }, + // 输入框内容对齐方式,可选值为:left|center|right + inputAlign: { + type: String, + default: uni.$u.props.input.inputAlign + }, + // 输入框字体的大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.input.fontSize + }, + // 输入框字体颜色 + color: { + type: String, + default: uni.$u.props.input.color + }, + // 输入框前置图标 + prefixIcon: { + type: String, + default: uni.$u.props.input.prefixIcon + }, + // 前置图标样式,对象或字符串 + prefixIconStyle: { + type: [String, Object], + default: uni.$u.props.input.prefixIconStyle + }, + // 输入框后置图标 + suffixIcon: { + type: String, + default: uni.$u.props.input.suffixIcon + }, + // 后置图标样式,对象或字符串 + suffixIconStyle: { + type: [String, Object], + default: uni.$u.props.input.suffixIconStyle + }, + // 边框类型,surround-四周边框,bottom-底部边框,none-无边框 + border: { + type: String, + default: uni.$u.props.input.border + }, + // 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会 + readonly: { + type: Boolean, + default: uni.$u.props.input.readonly + }, + // 输入框形状,circle-圆形,square-方形 + shape: { + type: String, + default: uni.$u.props.input.shape + }, + // 用于处理或者过滤输入框内容的方法 + formatter: { + type: [Function, null], + default: uni.$u.props.input.formatter + }, + // 是否忽略组件内对文本合成系统事件的处理 + ignoreCompositionEvent: { + type: Boolean, + default: true + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-input/u-input.vue b/yanzhu-ui-app/uview-ui/components/u-input/u-input.vue new file mode 100644 index 00000000..30073eb2 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-input/u-input.vue @@ -0,0 +1,354 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-keyboard/props.js b/yanzhu-ui-app/uview-ui/components/u-keyboard/props.js new file mode 100644 index 00000000..cfdb00ac --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-keyboard/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // 键盘的类型,number-数字键盘,card-身份证键盘,car-车牌号键盘 + mode: { + type: String, + default: uni.$u.props.keyboard.mode + }, + // 是否显示键盘的"."符号 + dotDisabled: { + type: Boolean, + default: uni.$u.props.keyboard.dotDisabled + }, + // 是否显示顶部工具条 + tooltip: { + type: Boolean, + default: uni.$u.props.keyboard.tooltip + }, + // 是否显示工具条中间的提示 + showTips: { + type: Boolean, + default: uni.$u.props.keyboard.showTips + }, + // 工具条中间的提示文字 + tips: { + type: String, + default: uni.$u.props.keyboard.tips + }, + // 是否显示工具条左边的"取消"按钮 + showCancel: { + type: Boolean, + default: uni.$u.props.keyboard.showCancel + }, + // 是否显示工具条右边的"完成"按钮 + showConfirm: { + type: Boolean, + default: uni.$u.props.keyboard.showConfirm + }, + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: uni.$u.props.keyboard.random + }, + // 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距 + safeAreaInsetBottom: { + type: Boolean, + default: uni.$u.props.keyboard.safeAreaInsetBottom + }, + // 是否允许通过点击遮罩关闭键盘 + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.keyboard.closeOnClickOverlay + }, + // 控制键盘的弹出与收起 + show: { + type: Boolean, + default: uni.$u.props.keyboard.show + }, + // 是否显示遮罩,某些时候数字键盘时,用户希望看到自己的数值,所以可能不想要遮罩 + overlay: { + type: Boolean, + default: uni.$u.props.keyboard.overlay + }, + // z-index值 + zIndex: { + type: [String, Number], + default: uni.$u.props.keyboard.zIndex + }, + // 取消按钮的文字 + cancelText: { + type: String, + default: uni.$u.props.keyboard.cancelText + }, + // 确认按钮的文字 + confirmText: { + type: String, + default: uni.$u.props.keyboard.confirmText + }, + // 输入一个中文后,是否自动切换到英文 + autoChange: { + type: Boolean, + default: uni.$u.props.keyboard.autoChange + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-keyboard/u-keyboard.vue b/yanzhu-ui-app/uview-ui/components/u-keyboard/u-keyboard.vue new file mode 100644 index 00000000..14228cbf --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-keyboard/u-keyboard.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-line-progress/props.js b/yanzhu-ui-app/uview-ui/components/u-line-progress/props.js new file mode 100644 index 00000000..a4210bdf --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-line-progress/props.js @@ -0,0 +1,28 @@ +export default { + props: { + // 激活部分的颜色 + activeColor: { + type: String, + default: uni.$u.props.lineProgress.activeColor + }, + inactiveColor: { + type: String, + default: uni.$u.props.lineProgress.color + }, + // 进度百分比,数值 + percentage: { + type: [String, Number], + default: uni.$u.props.lineProgress.inactiveColor + }, + // 是否在进度条内部显示百分比的值 + showText: { + type: Boolean, + default: uni.$u.props.lineProgress.showText + }, + // 进度条的高度,单位px + height: { + type: [String, Number], + default: uni.$u.props.lineProgress.height + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-line-progress/u-line-progress.vue b/yanzhu-ui-app/uview-ui/components/u-line-progress/u-line-progress.vue new file mode 100644 index 00000000..4e279310 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-line-progress/u-line-progress.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-line/props.js b/yanzhu-ui-app/uview-ui/components/u-line/props.js new file mode 100644 index 00000000..2308cc36 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-line/props.js @@ -0,0 +1,33 @@ +export default { + props: { + color: { + type: String, + default: uni.$u.props.line.color + }, + // 长度,竖向时表现为高度,横向时表现为长度,可以为百分比,带px单位的值等 + length: { + type: [String, Number], + default: uni.$u.props.line.length + }, + // 线条方向,col-竖向,row-横向 + direction: { + type: String, + default: uni.$u.props.line.direction + }, + // 是否显示细边框 + hairline: { + type: Boolean, + default: uni.$u.props.line.hairline + }, + // 线条与上下左右元素的间距,字符串形式,如"30px"、"20px 30px" + margin: { + type: [String, Number], + default: uni.$u.props.line.margin + }, + // 是否虚线,true-虚线,false-实线 + dashed: { + type: Boolean, + default: uni.$u.props.line.dashed + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-line/u-line.vue b/yanzhu-ui-app/uview-ui/components/u-line/u-line.vue new file mode 100644 index 00000000..e0a6d925 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-line/u-line.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-link/props.js b/yanzhu-ui-app/uview-ui/components/u-link/props.js new file mode 100644 index 00000000..d39353f1 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-link/props.js @@ -0,0 +1,39 @@ +export default { + props: { + // 文字颜色 + color: { + type: String, + default: uni.$u.props.link.color + }, + // 字体大小,单位px + fontSize: { + type: [String, Number], + default: uni.$u.props.link.fontSize + }, + // 是否显示下划线 + underLine: { + type: Boolean, + default: uni.$u.props.link.underLine + }, + // 要跳转的链接 + href: { + type: String, + default: uni.$u.props.link.href + }, + // 小程序中复制到粘贴板的提示语 + mpTips: { + type: String, + default: uni.$u.props.link.mpTips + }, + // 下划线颜色 + lineColor: { + type: String, + default: uni.$u.props.link.lineColor + }, + // 超链接的问题,不使用slot形式传入,是因为nvue下无法修改颜色 + text: { + type: String, + default: uni.$u.props.link.text + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-link/u-link.vue b/yanzhu-ui-app/uview-ui/components/u-link/u-link.vue new file mode 100644 index 00000000..c6802a56 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-link/u-link.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-list-item/props.js b/yanzhu-ui-app/uview-ui/components/u-list-item/props.js new file mode 100644 index 00000000..58ddc493 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-list-item/props.js @@ -0,0 +1,9 @@ +export default { + props: { + // 用于滚动到指定item + anchor: { + type: [String, Number], + default: uni.$u.props.listItem.anchor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-list-item/u-list-item.vue b/yanzhu-ui-app/uview-ui/components/u-list-item/u-list-item.vue new file mode 100644 index 00000000..1a25db65 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-list-item/u-list-item.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-list/props.js b/yanzhu-ui-app/uview-ui/components/u-list/props.js new file mode 100644 index 00000000..25406f4e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-list/props.js @@ -0,0 +1,76 @@ +export default { + props: { + // 控制是否出现滚动条,仅nvue有效 + showScrollbar: { + type: Boolean, + default: uni.$u.props.list.showScrollbar + }, + // 距底部多少时触发scrolltolower事件 + lowerThreshold: { + type: [String, Number], + default: uni.$u.props.list.lowerThreshold + }, + // 距顶部多少时触发scrolltoupper事件,非nvue有效 + upperThreshold: { + type: [String, Number], + default: uni.$u.props.list.upperThreshold + }, + // 设置竖向滚动条位置 + scrollTop: { + type: [String, Number], + default: uni.$u.props.list.scrollTop + }, + // 控制 onscroll 事件触发的频率,仅nvue有效 + offsetAccuracy: { + type: [String, Number], + default: uni.$u.props.list.offsetAccuracy + }, + // 启用 flexbox 布局。开启后,当前节点声明了display: flex就会成为flex container,并作用于其孩子节点,仅微信小程序有效 + enableFlex: { + type: Boolean, + default: uni.$u.props.list.enableFlex + }, + // 是否按分页模式显示List,默认值false + pagingEnabled: { + type: Boolean, + default: uni.$u.props.list.pagingEnabled + }, + // 是否允许List滚动 + scrollable: { + type: Boolean, + default: uni.$u.props.list.scrollable + }, + // 值应为某子元素id(id不能以数字开头) + scrollIntoView: { + type: String, + default: uni.$u.props.list.scrollIntoView + }, + // 在设置滚动条位置时使用动画过渡 + scrollWithAnimation: { + type: Boolean, + default: uni.$u.props.list.scrollWithAnimation + }, + // iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只对微信小程序有效 + enableBackToTop: { + type: Boolean, + default: uni.$u.props.list.enableBackToTop + }, + // 列表的高度 + height: { + type: [String, Number], + default: uni.$u.props.list.height + }, + // 列表宽度 + width: { + type: [String, Number], + default: uni.$u.props.list.width + }, + // 列表前后预渲染的屏数,1代表一个屏幕的高度,1.5代表1个半屏幕高度 + preLoadScreen: { + type: [String, Number], + default: uni.$u.props.list.preLoadScreen + } + // vue下,是否开启虚拟列表 + + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-list/u-list.vue b/yanzhu-ui-app/uview-ui/components/u-list/u-list.vue new file mode 100644 index 00000000..4447cab6 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-list/u-list.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-loading-icon/props.js b/yanzhu-ui-app/uview-ui/components/u-loading-icon/props.js new file mode 100644 index 00000000..c35524e2 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loading-icon/props.js @@ -0,0 +1,59 @@ +export default { + props: { + // 是否显示组件 + show: { + type: Boolean, + default: uni.$u.props.loadingIcon.show + }, + // 颜色 + color: { + type: String, + default: uni.$u.props.loadingIcon.color + }, + // 提示文字颜色 + textColor: { + type: String, + default: uni.$u.props.loadingIcon.textColor + }, + // 文字和图标是否垂直排列 + vertical: { + type: Boolean, + default: uni.$u.props.loadingIcon.vertical + }, + // 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形 + mode: { + type: String, + default: uni.$u.props.loadingIcon.mode + }, + // 图标大小,单位默认px + size: { + type: [String, Number], + default: uni.$u.props.loadingIcon.size + }, + // 文字大小 + textSize: { + type: [String, Number], + default: uni.$u.props.loadingIcon.textSize + }, + // 文字内容 + text: { + type: [String, Number], + default: uni.$u.props.loadingIcon.text + }, + // 动画模式 + timingFunction: { + type: String, + default: uni.$u.props.loadingIcon.timingFunction + }, + // 动画执行周期时间 + duration: { + type: [String, Number], + default: uni.$u.props.loadingIcon.duration + }, + // mode=circle时的暗边颜色 + inactiveColor: { + type: String, + default: uni.$u.props.loadingIcon.inactiveColor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-loading-icon/u-loading-icon.vue b/yanzhu-ui-app/uview-ui/components/u-loading-icon/u-loading-icon.vue new file mode 100644 index 00000000..2ede5c3a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loading-icon/u-loading-icon.vue @@ -0,0 +1,343 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-loading-page/props.js b/yanzhu-ui-app/uview-ui/components/u-loading-page/props.js new file mode 100644 index 00000000..e239b612 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loading-page/props.js @@ -0,0 +1,49 @@ +export default { + props: { + // 提示内容 + loadingText: { + type: [String, Number], + default: uni.$u.props.loadingPage.loadingText + }, + // 文字上方用于替换loading动画的图片 + image: { + type: String, + default: uni.$u.props.loadingPage.image + }, + // 加载动画的模式,circle-圆形,spinner-花朵形,semicircle-半圆形 + loadingMode: { + type: String, + default: uni.$u.props.loadingPage.loadingMode + }, + // 是否加载中 + loading: { + type: Boolean, + default: uni.$u.props.loadingPage.loading + }, + // 背景色 + bgColor: { + type: String, + default: uni.$u.props.loadingPage.bgColor + }, + // 文字颜色 + color: { + type: String, + default: uni.$u.props.loadingPage.color + }, + // 文字大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.loadingPage.fontSize + }, + // 图标大小 + iconSize: { + type: [String, Number], + default: uni.$u.props.loadingPage.fontSize + }, + // 加载中图标的颜色,只能rgb或者十六进制颜色值 + loadingColor: { + type: String, + default: uni.$u.props.loadingPage.loadingColor + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-loading-page/u-loading-page.vue b/yanzhu-ui-app/uview-ui/components/u-loading-page/u-loading-page.vue new file mode 100644 index 00000000..03a78ad8 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loading-page/u-loading-page.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-loadmore/props.js b/yanzhu-ui-app/uview-ui/components/u-loadmore/props.js new file mode 100644 index 00000000..1e67d891 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loadmore/props.js @@ -0,0 +1,94 @@ +export default { + props: { + // 组件状态,loadmore-加载前的状态,loading-加载中的状态,nomore-没有更多的状态 + status: { + type: String, + default: uni.$u.props.loadmore.status + }, + // 组件背景色 + bgColor: { + type: String, + default: uni.$u.props.loadmore.bgColor + }, + // 是否显示加载中的图标 + icon: { + type: Boolean, + default: uni.$u.props.loadmore.icon + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.loadmore.fontSize + }, + // 图标大小 + iconSize: { + type: [String, Number], + default: uni.$u.props.loadmore.iconSize + }, + // 字体颜色 + color: { + type: String, + default: uni.$u.props.loadmore.color + }, + // 加载中状态的图标,spinner-花朵状图标,circle-圆圈状,semicircle-半圆 + loadingIcon: { + type: String, + default: uni.$u.props.loadmore.loadingIcon + }, + // 加载前的提示语 + loadmoreText: { + type: String, + default: uni.$u.props.loadmore.loadmoreText + }, + // 加载中提示语 + loadingText: { + type: String, + default: uni.$u.props.loadmore.loadingText + }, + // 没有更多的提示语 + nomoreText: { + type: String, + default: uni.$u.props.loadmore.nomoreText + }, + // 在“没有更多”状态下,是否显示粗点 + isDot: { + type: Boolean, + default: uni.$u.props.loadmore.isDot + }, + // 加载中图标的颜色 + iconColor: { + type: String, + default: uni.$u.props.loadmore.iconColor + }, + // 上边距 + marginTop: { + type: [String, Number], + default: uni.$u.props.loadmore.marginTop + }, + // 下边距 + marginBottom: { + type: [String, Number], + default: uni.$u.props.loadmore.marginBottom + }, + // 高度,单位px + height: { + type: [String, Number], + default: uni.$u.props.loadmore.height + }, + // 是否显示左边分割线 + line: { + type: Boolean, + default: uni.$u.props.loadmore.line + }, + // 线条颜色 + lineColor: { + type: String, + default: uni.$u.props.loadmore.lineColor + }, + // 是否虚线,true-虚线,false-实线 + dashed: { + type: Boolean, + default: uni.$u.props.loadmore.dashed + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-loadmore/u-loadmore.vue b/yanzhu-ui-app/uview-ui/components/u-loadmore/u-loadmore.vue new file mode 100644 index 00000000..73c79fef --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-loadmore/u-loadmore.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-modal/props.js b/yanzhu-ui-app/uview-ui/components/u-modal/props.js new file mode 100644 index 00000000..f76672c8 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-modal/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // 是否展示modal + show: { + type: Boolean, + default: uni.$u.props.modal.show + }, + // 标题 + title: { + type: [String], + default: uni.$u.props.modal.title + }, + // 弹窗内容 + content: { + type: String, + default: uni.$u.props.modal.content + }, + // 确认文案 + confirmText: { + type: String, + default: uni.$u.props.modal.confirmText + }, + // 取消文案 + cancelText: { + type: String, + default: uni.$u.props.modal.cancelText + }, + // 是否显示确认按钮 + showConfirmButton: { + type: Boolean, + default: uni.$u.props.modal.showConfirmButton + }, + // 是否显示取消按钮 + showCancelButton: { + type: Boolean, + default: uni.$u.props.modal.showCancelButton + }, + // 确认按钮颜色 + confirmColor: { + type: String, + default: uni.$u.props.modal.confirmColor + }, + // 取消文字颜色 + cancelColor: { + type: String, + default: uni.$u.props.modal.cancelColor + }, + // 对调确认和取消的位置 + buttonReverse: { + type: Boolean, + default: uni.$u.props.modal.buttonReverse + }, + // 是否开启缩放效果 + zoom: { + type: Boolean, + default: uni.$u.props.modal.zoom + }, + // 是否异步关闭,只对确定按钮有效 + asyncClose: { + type: Boolean, + default: uni.$u.props.modal.asyncClose + }, + // 是否允许点击遮罩关闭modal + closeOnClickOverlay: { + type: Boolean, + default: uni.$u.props.modal.closeOnClickOverlay + }, + // 给一个负的margin-top,往上偏移,避免和键盘重合的情况 + negativeTop: { + type: [String, Number], + default: uni.$u.props.modal.negativeTop + }, + // modal宽度,不支持百分比,可以数值,px,rpx单位 + width: { + type: [String, Number], + default: uni.$u.props.modal.width + }, + // 确认按钮的样式,circle-圆形,square-方形,如设置,将不会显示取消按钮 + confirmButtonShape: { + type: String, + default: uni.$u.props.modal.confirmButtonShape + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-modal/u-modal.vue b/yanzhu-ui-app/uview-ui/components/u-modal/u-modal.vue new file mode 100644 index 00000000..2cbc7370 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-modal/u-modal.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-navbar/props.js b/yanzhu-ui-app/uview-ui/components/u-navbar/props.js new file mode 100644 index 00000000..5398de28 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-navbar/props.js @@ -0,0 +1,84 @@ +export default { + props: { + // 是否开启顶部安全区适配 + safeAreaInsetTop: { + type: Boolean, + default: uni.$u.props.navbar.safeAreaInsetTop + }, + // 固定在顶部时,是否生成一个等高元素,以防止塌陷 + placeholder: { + type: Boolean, + default: uni.$u.props.navbar.placeholder + }, + // 是否固定在顶部 + fixed: { + type: Boolean, + default: uni.$u.props.navbar.fixed + }, + // 是否显示下边框 + border: { + type: Boolean, + default: uni.$u.props.navbar.border + }, + // 左边的图标 + leftIcon: { + type: String, + default: uni.$u.props.navbar.leftIcon + }, + // 左边的提示文字 + leftText: { + type: String, + default: uni.$u.props.navbar.leftText + }, + // 左右的提示文字 + rightText: { + type: String, + default: uni.$u.props.navbar.rightText + }, + // 右边的图标 + rightIcon: { + type: String, + default: uni.$u.props.navbar.rightIcon + }, + // 标题 + title: { + type: [String, Number], + default: uni.$u.props.navbar.title + }, + // 背景颜色 + bgColor: { + type: String, + default: uni.$u.props.navbar.bgColor + }, + // 标题的宽度 + titleWidth: { + type: [String, Number], + default: uni.$u.props.navbar.titleWidth + }, + // 导航栏高度 + height: { + type: [String, Number], + default: uni.$u.props.navbar.height + }, + // 左侧返回图标的大小 + leftIconSize: { + type: [String, Number], + default: uni.$u.props.navbar.leftIconSize + }, + // 左侧返回图标的颜色 + leftIconColor: { + type: String, + default: uni.$u.props.navbar.leftIconColor + }, + // 点击左侧区域(返回图标),是否自动返回上一页 + autoBack: { + type: Boolean, + default: uni.$u.props.navbar.autoBack + }, + // 标题的样式,对象或字符串 + titleStyle: { + type: [String, Object], + default: uni.$u.props.navbar.titleStyle + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-navbar/u-navbar.vue b/yanzhu-ui-app/uview-ui/components/u-navbar/u-navbar.vue new file mode 100644 index 00000000..2b206b7d --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-navbar/u-navbar.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-no-network/props.js b/yanzhu-ui-app/uview-ui/components/u-no-network/props.js new file mode 100644 index 00000000..9f3af62c --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-no-network/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // 页面文字提示 + tips: { + type: String, + default: uni.$u.props.noNetwork.tips + }, + // 一个z-index值,用于设置没有网络这个组件的层次,因为页面可能会有其他定位的元素层级过高,导致此组件被覆盖 + zIndex: { + type: [String, Number], + default: uni.$u.props.noNetwork.zIndex + }, + // image 没有网络的图片提示 + image: { + type: String, + default: uni.$u.props.noNetwork.image + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-no-network/u-no-network.vue b/yanzhu-ui-app/uview-ui/components/u-no-network/u-no-network.vue new file mode 100644 index 00000000..9710729e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-no-network/u-no-network.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-notice-bar/props.js b/yanzhu-ui-app/uview-ui/components/u-notice-bar/props.js new file mode 100644 index 00000000..7040c29a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-notice-bar/props.js @@ -0,0 +1,70 @@ +export default { + props: { + // 显示的内容,数组 + text: { + type: [Array, String], + default: uni.$u.props.noticeBar.text + }, + // 通告滚动模式,row-横向滚动,column-竖向滚动 + direction: { + type: String, + default: uni.$u.props.noticeBar.direction + }, + // direction = row时,是否使用步进形式滚动 + step: { + type: Boolean, + default: uni.$u.props.noticeBar.step + }, + // 是否显示左侧的音量图标 + icon: { + type: String, + default: uni.$u.props.noticeBar.icon + }, + // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 + mode: { + type: String, + default: uni.$u.props.noticeBar.mode + }, + // 文字颜色,各图标也会使用文字颜色 + color: { + type: String, + default: uni.$u.props.noticeBar.color + }, + // 背景颜色 + bgColor: { + type: String, + default: uni.$u.props.noticeBar.bgColor + }, + // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 + speed: { + type: [String, Number], + default: uni.$u.props.noticeBar.speed + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.noticeBar.fontSize + }, + // 滚动一个周期的时间长,单位ms + duration: { + type: [String, Number], + default: uni.$u.props.noticeBar.duration + }, + // 是否禁止用手滑动切换 + // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 + disableTouch: { + type: Boolean, + default: uni.$u.props.noticeBar.disableTouch + }, + // 跳转的页面路径 + url: { + type: String, + default: uni.$u.props.noticeBar.url + }, + // 页面跳转的类型 + linkType: { + type: String, + default: uni.$u.props.noticeBar.linkType + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-notice-bar/u-notice-bar.vue b/yanzhu-ui-app/uview-ui/components/u-notice-bar/u-notice-bar.vue new file mode 100644 index 00000000..a06eb39a --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-notice-bar/u-notice-bar.vue @@ -0,0 +1,101 @@ + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-notify/props.js b/yanzhu-ui-app/uview-ui/components/u-notify/props.js new file mode 100644 index 00000000..57a9d71e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-notify/props.js @@ -0,0 +1,49 @@ +export default { + props: { + // 到顶部的距离 + top: { + type: [String, Number], + default: uni.$u.props.notify.top + }, + // 是否展示组件 + // show: { + // type: Boolean, + // default: uni.$u.props.notify.show + // }, + // type主题,primary,success,warning,error + type: { + type: String, + default: uni.$u.props.notify.type + }, + // 字体颜色 + color: { + type: String, + default: uni.$u.props.notify.color + }, + // 背景颜色 + bgColor: { + type: String, + default: uni.$u.props.notify.bgColor + }, + // 展示的文字内容 + message: { + type: String, + default: uni.$u.props.notify.message + }, + // 展示时长,为0时不消失,单位ms + duration: { + type: [String, Number], + default: uni.$u.props.notify.duration + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: uni.$u.props.notify.fontSize + }, + // 是否留出顶部安全距离(状态栏高度) + safeAreaInsetTop: { + type: Boolean, + default: uni.$u.props.notify.safeAreaInsetTop + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-notify/u-notify.vue b/yanzhu-ui-app/uview-ui/components/u-notify/u-notify.vue new file mode 100644 index 00000000..30adb72f --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-notify/u-notify.vue @@ -0,0 +1,211 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-number-box/props.js b/yanzhu-ui-app/uview-ui/components/u-number-box/props.js new file mode 100644 index 00000000..fb0fa947 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-number-box/props.js @@ -0,0 +1,109 @@ +export default { + props: { + // 步进器标识符,在change回调返回 + name: { + type: [String, Number], + default: uni.$u.props.numberBox.name + }, + // 用于双向绑定的值,初始化时设置设为默认min值(最小值) + value: { + type: [String, Number], + default: uni.$u.props.numberBox.value + }, + // 最小值 + min: { + type: [String, Number], + default: uni.$u.props.numberBox.min + }, + // 最大值 + max: { + type: [String, Number], + default: uni.$u.props.numberBox.max + }, + // 加减的步长,可为小数 + step: { + type: [String, Number], + default: uni.$u.props.numberBox.step + }, + // 是否只允许输入整数 + integer: { + type: Boolean, + default: uni.$u.props.numberBox.integer + }, + // 是否禁用,包括输入框,加减按钮 + disabled: { + type: Boolean, + default: uni.$u.props.numberBox.disabled + }, + // 是否禁用输入框 + disabledInput: { + type: Boolean, + default: uni.$u.props.numberBox.disabledInput + }, + // 是否开启异步变更,开启后需要手动控制输入值 + asyncChange: { + type: Boolean, + default: uni.$u.props.numberBox.asyncChange + }, + // 输入框宽度,单位为px + inputWidth: { + type: [String, Number], + default: uni.$u.props.numberBox.inputWidth + }, + // 是否显示减少按钮 + showMinus: { + type: Boolean, + default: uni.$u.props.numberBox.showMinus + }, + // 是否显示增加按钮 + showPlus: { + type: Boolean, + default: uni.$u.props.numberBox.showPlus + }, + // 显示的小数位数 + decimalLength: { + type: [String, Number, null], + default: uni.$u.props.numberBox.decimalLength + }, + // 是否开启长按加减手势 + longPress: { + type: Boolean, + default: uni.$u.props.numberBox.longPress + }, + // 输入框文字和加减按钮图标的颜色 + color: { + type: String, + default: uni.$u.props.numberBox.color + }, + // 按钮大小,宽高等于此值,单位px,输入框高度和此值保持一致 + buttonSize: { + type: [String, Number], + default: uni.$u.props.numberBox.buttonSize + }, + // 输入框和按钮的背景颜色 + bgColor: { + type: String, + default: uni.$u.props.numberBox.bgColor + }, + // 指定光标于键盘的距离,避免键盘遮挡输入框,单位px + cursorSpacing: { + type: [String, Number], + default: uni.$u.props.numberBox.cursorSpacing + }, + // 是否禁用增加按钮 + disablePlus: { + type: Boolean, + default: uni.$u.props.numberBox.disablePlus + }, + // 是否禁用减少按钮 + disableMinus: { + type: Boolean, + default: uni.$u.props.numberBox.disableMinus + }, + // 加减按钮图标的样式 + iconStyle: { + type: [Object, String], + default: uni.$u.props.numberBox.iconStyle + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-number-box/u-number-box.vue b/yanzhu-ui-app/uview-ui/components/u-number-box/u-number-box.vue new file mode 100644 index 00000000..69211c54 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-number-box/u-number-box.vue @@ -0,0 +1,416 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-number-keyboard/props.js b/yanzhu-ui-app/uview-ui/components/u-number-keyboard/props.js new file mode 100644 index 00000000..5e3bf556 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-number-keyboard/props.js @@ -0,0 +1,19 @@ +export default { + props: { + // 键盘的类型,number-数字键盘,card-身份证键盘 + mode: { + type: String, + default: uni.$u.props.numberKeyboard.value + }, + // 是否显示键盘的"."符号 + dotDisabled: { + type: Boolean, + default: uni.$u.props.numberKeyboard.dotDisabled + }, + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: uni.$u.props.numberKeyboard.random + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-number-keyboard/u-number-keyboard.vue b/yanzhu-ui-app/uview-ui/components/u-number-keyboard/u-number-keyboard.vue new file mode 100644 index 00000000..4f505c6e --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-number-keyboard/u-number-keyboard.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-overlay/props.js b/yanzhu-ui-app/uview-ui/components/u-overlay/props.js new file mode 100644 index 00000000..e6974df9 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-overlay/props.js @@ -0,0 +1,24 @@ +export default { + props: { + // 是否显示遮罩 + show: { + type: Boolean, + default: uni.$u.props.overlay.show + }, + // 层级z-index + zIndex: { + type: [String, Number], + default: uni.$u.props.overlay.zIndex + }, + // 遮罩的过渡时间,单位为ms + duration: { + type: [String, Number], + default: uni.$u.props.overlay.duration + }, + // 不透明度值,当做rgba的第四个参数 + opacity: { + type: [String, Number], + default: uni.$u.props.overlay.opacity + } + } +} diff --git a/yanzhu-ui-app/uview-ui/components/u-overlay/u-overlay.vue b/yanzhu-ui-app/uview-ui/components/u-overlay/u-overlay.vue new file mode 100644 index 00000000..92de4e9f --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-overlay/u-overlay.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/yanzhu-ui-app/uview-ui/components/u-parse/node/node.vue b/yanzhu-ui-app/uview-ui/components/u-parse/node/node.vue new file mode 100644 index 00000000..73e30fd6 --- /dev/null +++ b/yanzhu-ui-app/uview-ui/components/u-parse/node/node.vue @@ -0,0 +1,499 @@ + + + diff --git a/yanzhu-ui-vue3/src/layout/components/Navbar.vue b/yanzhu-ui-vue3/src/layout/components/Navbar.vue new file mode 100644 index 00000000..ab4d5f36 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Navbar.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/yanzhu-ui-vue3/src/layout/components/Settings/index.vue b/yanzhu-ui-vue3/src/layout/components/Settings/index.vue new file mode 100644 index 00000000..3360959c --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Settings/index.vue @@ -0,0 +1,241 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/layout/components/Sidebar/Link.vue b/yanzhu-ui-vue3/src/layout/components/Sidebar/Link.vue new file mode 100644 index 00000000..80114316 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Sidebar/Link.vue @@ -0,0 +1,40 @@ + + + diff --git a/yanzhu-ui-vue3/src/layout/components/Sidebar/Logo.vue b/yanzhu-ui-vue3/src/layout/components/Sidebar/Logo.vue new file mode 100644 index 00000000..934d13d9 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Sidebar/Logo.vue @@ -0,0 +1,81 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/layout/components/Sidebar/SidebarItem.vue b/yanzhu-ui-vue3/src/layout/components/Sidebar/SidebarItem.vue new file mode 100644 index 00000000..c423fb18 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Sidebar/SidebarItem.vue @@ -0,0 +1,102 @@ + + + diff --git a/yanzhu-ui-vue3/src/layout/components/Sidebar/index.vue b/yanzhu-ui-vue3/src/layout/components/Sidebar/index.vue new file mode 100644 index 00000000..9b14dfc0 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/Sidebar/index.vue @@ -0,0 +1,54 @@ + + + diff --git a/yanzhu-ui-vue3/src/layout/components/TagsView/ScrollPane.vue b/yanzhu-ui-vue3/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 00000000..5c2977a0 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,105 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/layout/components/TagsView/index.vue b/yanzhu-ui-vue3/src/layout/components/TagsView/index.vue new file mode 100644 index 00000000..1f996234 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/TagsView/index.vue @@ -0,0 +1,338 @@ + + + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/layout/components/index.js b/yanzhu-ui-vue3/src/layout/components/index.js new file mode 100644 index 00000000..fd577313 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/components/index.js @@ -0,0 +1,4 @@ +export { default as AppMain } from './AppMain' +export { default as Navbar } from './Navbar' +export { default as Settings } from './Settings' +export { default as TagsView } from './TagsView/index.vue' diff --git a/yanzhu-ui-vue3/src/layout/index.vue b/yanzhu-ui-vue3/src/layout/index.vue new file mode 100644 index 00000000..3ddb1657 --- /dev/null +++ b/yanzhu-ui-vue3/src/layout/index.vue @@ -0,0 +1,111 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/main.js b/yanzhu-ui-vue3/src/main.js new file mode 100644 index 00000000..5cf88464 --- /dev/null +++ b/yanzhu-ui-vue3/src/main.js @@ -0,0 +1,83 @@ +import { createApp } from 'vue' + +import Cookies from 'js-cookie' + +import ElementPlus from 'element-plus' +import locale from 'element-plus/lib/locale/lang/zh-cn' // 中文语言 + +import '@/assets/styles/index.scss' // global css + +import App from './App' +import store from './store' +import router from './router' +import directive from './directive' // directive + +// 注册指令 +import plugins from './plugins' // plugins +import { download } from '@/utils/request' + +// svg图标 +import 'virtual:svg-icons-register' +import SvgIcon from '@/components/SvgIcon' +import elementIcons from '@/components/SvgIcon/svgicon' + +import './permission' // permission control + +import { useDict } from '@/utils/dict' +import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi' + +// 分页组件 +import Pagination from '@/components/Pagination' +// 自定义表格工具组件 +import RightToolbar from '@/components/RightToolbar' +// 富文本组件 +import Editor from "@/components/Editor" +// 文件上传组件 +import FileUpload from "@/components/FileUpload" +// 图片上传组件 +import ImageUpload from "@/components/ImageUpload" +// 图片预览组件 +import ImagePreview from "@/components/ImagePreview" +// 自定义树选择组件 +import TreeSelect from '@/components/TreeSelect' +// 字典标签组件 +import DictTag from '@/components/DictTag' + +const app = createApp(App) + +// 全局方法挂载 +app.config.globalProperties.useDict = useDict +app.config.globalProperties.download = download +app.config.globalProperties.parseTime = parseTime +app.config.globalProperties.resetForm = resetForm +app.config.globalProperties.handleTree = handleTree +app.config.globalProperties.addDateRange = addDateRange +app.config.globalProperties.selectDictLabel = selectDictLabel +app.config.globalProperties.selectDictLabels = selectDictLabels + +// 全局组件挂载 +app.component('DictTag', DictTag) +app.component('Pagination', Pagination) +app.component('TreeSelect', TreeSelect) +app.component('FileUpload', FileUpload) +app.component('ImageUpload', ImageUpload) +app.component('ImagePreview', ImagePreview) +app.component('RightToolbar', RightToolbar) +app.component('Editor', Editor) + +app.use(router) +app.use(store) +app.use(plugins) +app.use(elementIcons) +app.component('svg-icon', SvgIcon) + +directive(app) + +// 使用element-plus 并且设置全局的大小 +app.use(ElementPlus, { + locale: locale, + // 支持 large、default、small + size: Cookies.get('size') || 'default' +}) + +app.mount('#app') diff --git a/yanzhu-ui-vue3/src/permission.js b/yanzhu-ui-vue3/src/permission.js new file mode 100644 index 00000000..a474e0e6 --- /dev/null +++ b/yanzhu-ui-vue3/src/permission.js @@ -0,0 +1,63 @@ +import router from './router' +import { ElMessage } from 'element-plus' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { getToken } from '@/utils/auth' +import { isHttp } from '@/utils/validate' +import { isRelogin } from '@/utils/request' +import useUserStore from '@/store/modules/user' +import useSettingsStore from '@/store/modules/settings' +import usePermissionStore from '@/store/modules/permission' + +NProgress.configure({ showSpinner: false }); + +const whiteList = ['/login', '/register']; + +router.beforeEach((to, from, next) => { + NProgress.start() + if (getToken()) { + to.meta.title && useSettingsStore().setTitle(to.meta.title) + /* has token*/ + if (to.path === '/login') { + next({ path: '/' }) + NProgress.done() + } else { + if (useUserStore().roles.length === 0) { + isRelogin.show = true + // 判断当前用户是否已拉取完user_info信息 + useUserStore().getInfo().then(() => { + isRelogin.show = false + usePermissionStore().generateRoutes().then(accessRoutes => { + // 根据roles权限生成可访问的路由表 + accessRoutes.forEach(route => { + if (!isHttp(route.path)) { + router.addRoute(route) // 动态添加可访问路由表 + } + }) + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 + }) + }).catch(err => { + useUserStore().logOut().then(() => { + ElMessage.error(err) + next({ path: '/' }) + }) + }) + } else { + next() + } + } + } else { + // 没有token + if (whiteList.indexOf(to.path) !== -1) { + // 在免登录白名单,直接进入 + next() + } else { + next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() +}) diff --git a/yanzhu-ui-vue3/src/plugins/auth.js b/yanzhu-ui-vue3/src/plugins/auth.js new file mode 100644 index 00000000..5e8c28de --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/auth.js @@ -0,0 +1,60 @@ +import useUserStore from '@/store/modules/user' + +function authPermission(permission) { + const all_permission = "*:*:*"; + const permissions = useUserStore().permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "admin"; + const roles = useUserStore().roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 验证用户是否具备某权限 + hasPermi(permission) { + return authPermission(permission); + }, + // 验证用户是否含有指定权限,只需包含其中一个 + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 验证用户是否含有指定权限,必须全部拥有 + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 验证用户是否具备某角色 + hasRole(role) { + return authRole(role); + }, + // 验证用户是否含有指定角色,只需包含其中一个 + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 验证用户是否含有指定角色,必须全部拥有 + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} diff --git a/yanzhu-ui-vue3/src/plugins/cache.js b/yanzhu-ui-vue3/src/plugins/cache.js new file mode 100644 index 00000000..6b5c00b9 --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/cache.js @@ -0,0 +1,77 @@ +const sessionCache = { + set (key, value) { + if (!sessionStorage) { + return + } + if (key != null && value != null) { + sessionStorage.setItem(key, value) + } + }, + get (key) { + if (!sessionStorage) { + return null + } + if (key == null) { + return null + } + return sessionStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + sessionStorage.removeItem(key); + } +} +const localCache = { + set (key, value) { + if (!localStorage) { + return + } + if (key != null && value != null) { + localStorage.setItem(key, value) + } + }, + get (key) { + if (!localStorage) { + return null + } + if (key == null) { + return null + } + return localStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + localStorage.removeItem(key); + } +} + +export default { + /** + * 会话级缓存 + */ + session: sessionCache, + /** + * 本地缓存 + */ + local: localCache +} diff --git a/yanzhu-ui-vue3/src/plugins/download.js b/yanzhu-ui-vue3/src/plugins/download.js new file mode 100644 index 00000000..2dc6fb69 --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/download.js @@ -0,0 +1,38 @@ +import axios from 'axios' +import { ElMessage } from 'element-plus' +import { saveAs } from 'file-saver' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { blobValidate } from '@/utils/ruoyi' + +const baseURL = import.meta.env.VITE_APP_BASE_API + +export default { + zip(url, name) { + var url = baseURL + url + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + const blob = new Blob([res.data], { type: 'application/zip' }) + this.saveAs(blob, name) + } else { + this.printErrMsg(res.data); + } + }) + }, + saveAs(text, name, opts) { + saveAs(text, name, opts); + }, + async printErrMsg(data) { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + ElMessage.error(errMsg); + } +} + diff --git a/yanzhu-ui-vue3/src/plugins/index.js b/yanzhu-ui-vue3/src/plugins/index.js new file mode 100644 index 00000000..47d1b41f --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/index.js @@ -0,0 +1,18 @@ +import tab from './tab' +import auth from './auth' +import cache from './cache' +import modal from './modal' +import download from './download' + +export default function installPlugins(app){ + // 页签操作 + app.config.globalProperties.$tab = tab + // 认证对象 + app.config.globalProperties.$auth = auth + // 缓存对象 + app.config.globalProperties.$cache = cache + // 模态框对象 + app.config.globalProperties.$modal = modal + // 下载文件 + app.config.globalProperties.$download = download +} diff --git a/yanzhu-ui-vue3/src/plugins/modal.js b/yanzhu-ui-vue3/src/plugins/modal.js new file mode 100644 index 00000000..b59e14d6 --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/modal.js @@ -0,0 +1,82 @@ +import { ElMessage, ElMessageBox, ElNotification, ElLoading } from 'element-plus' + +let loadingInstance; + +export default { + // 消息提示 + msg(content) { + ElMessage.info(content) + }, + // 错误消息 + msgError(content) { + ElMessage.error(content) + }, + // 成功消息 + msgSuccess(content) { + ElMessage.success(content) + }, + // 警告消息 + msgWarning(content) { + ElMessage.warning(content) + }, + // 弹出提示 + alert(content) { + ElMessageBox.alert(content, "系统提示") + }, + // 错误提示 + alertError(content) { + ElMessageBox.alert(content, "系统提示", { type: 'error' }) + }, + // 成功提示 + alertSuccess(content) { + ElMessageBox.alert(content, "系统提示", { type: 'success' }) + }, + // 警告提示 + alertWarning(content) { + ElMessageBox.alert(content, "系统提示", { type: 'warning' }) + }, + // 通知提示 + notify(content) { + ElNotification.info(content) + }, + // 错误通知 + notifyError(content) { + ElNotification.error(content); + }, + // 成功通知 + notifySuccess(content) { + ElNotification.success(content) + }, + // 警告通知 + notifyWarning(content) { + ElNotification.warning(content) + }, + // 确认窗体 + confirm(content) { + return ElMessageBox.confirm(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 提交内容 + prompt(content) { + return ElMessageBox.prompt(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 打开遮罩层 + loading(content) { + loadingInstance = ElLoading.service({ + lock: true, + text: content, + background: "rgba(0, 0, 0, 0.7)", + }) + }, + // 关闭遮罩层 + closeLoading() { + loadingInstance.close(); + } +} diff --git a/yanzhu-ui-vue3/src/plugins/tab.js b/yanzhu-ui-vue3/src/plugins/tab.js new file mode 100644 index 00000000..59e7006b --- /dev/null +++ b/yanzhu-ui-vue3/src/plugins/tab.js @@ -0,0 +1,65 @@ +import useTagsViewStore from '@/store/modules/tagsView' +import router from '@/router' + +export default { + // 刷新当前tab页签 + refreshPage(obj) { + const { path, query, matched } = router.currentRoute.value; + if (obj === undefined) { + matched.forEach((m) => { + if (m.components && m.components.default && m.components.default.name) { + if (!['Layout', 'ParentView'].includes(m.components.default.name)) { + obj = { name: m.components.default.name, path: path, query: query }; + } + } + }); + } + return useTagsViewStore().delCachedView(obj).then(() => { + const { path, query } = obj + router.replace({ + path: '/redirect' + path, + query: query + }) + }) + }, + // 关闭当前tab页签,打开新页签 + closeOpenPage(obj) { + useTagsViewStore().delView(router.currentRoute.value); + if (obj !== undefined) { + return router.push(obj); + } + }, + // 关闭指定tab页签 + closePage(obj) { + if (obj === undefined) { + return useTagsViewStore().delView(router.currentRoute.value).then(({ lastPath }) => { + return router.push(lastPath || '/index'); + }); + } + return useTagsViewStore().delView(obj); + }, + // 关闭所有tab页签 + closeAllPage() { + return useTagsViewStore().delAllViews(); + }, + // 关闭左侧tab页签 + closeLeftPage(obj) { + return useTagsViewStore().delLeftTags(obj || router.currentRoute.value); + }, + // 关闭右侧tab页签 + closeRightPage(obj) { + return useTagsViewStore().delRightTags(obj || router.currentRoute.value); + }, + // 关闭其他tab页签 + closeOtherPage(obj) { + return useTagsViewStore().delOthersViews(obj || router.currentRoute.value); + }, + // 打开tab页签 + openPage(url) { + return router.push(url); + }, + // 修改tab页签 + updatePage(obj) { + return useTagsViewStore().updateVisitedView(obj); + } +} diff --git a/yanzhu-ui-vue3/src/router/index.js b/yanzhu-ui-vue3/src/router/index.js new file mode 100644 index 00000000..df4a0a82 --- /dev/null +++ b/yanzhu-ui-vue3/src/router/index.js @@ -0,0 +1,175 @@ +import { createWebHistory, createRouter } from 'vue-router' +/* Layout */ +import Layout from '@/layout' + +/** + * Note: 路由配置项 + * + * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1 + * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面 + * // 若你想不管路由下面的 children 声明的个数都显示你的根路由 + * // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由 + * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + * name:'router-name' // 设定路由的名字,一定要填写不然使用时会出现各种问题 + * query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数 + * roles: ['admin', 'common'] // 访问路由的角色权限 + * permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限 + * meta : { + noCache: true // 如果设置为true,则不会被 缓存(默认 false) + title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 + icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg + breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 + activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 + } + */ + +// 公共路由 +export const constantRoutes = [ + { + path: '/redirect', + component: Layout, + hidden: true, + children: [ + { + path: '/redirect/:path(.*)', + component: () => import('@/views/redirect/index.vue') + } + ] + }, + { + path: '/login', + component: () => import('@/views/login'), + hidden: true + }, + { + path: '/register', + component: () => import('@/views/register'), + hidden: true + }, + { + path: "/:pathMatch(.*)*", + component: () => import('@/views/error/404'), + hidden: true + }, + { + path: '/401', + component: () => import('@/views/error/401'), + hidden: true + }, + { + path: '', + component: Layout, + redirect: '/index', + children: [ + { + path: '/index', + component: () => import('@/views/index'), + name: 'Index', + meta: { title: '首页', icon: 'dashboard', affix: true } + } + ] + }, + { + path: '/user', + component: Layout, + hidden: true, + redirect: 'noredirect', + children: [ + { + path: 'profile', + component: () => import('@/views/system/user/profile/index'), + name: 'Profile', + meta: { title: '个人中心', icon: 'user' } + } + ] + } +] + +// 动态路由,基于用户权限动态去加载 +export const dynamicRoutes = [ + { + path: '/system/user-auth', + component: Layout, + hidden: true, + permissions: ['system:user:edit'], + children: [ + { + path: 'role/:userId(\\d+)', + component: () => import('@/views/system/user/authRole'), + name: 'AuthRole', + meta: { title: '分配角色', activeMenu: '/system/user' } + } + ] + }, + { + path: '/system/role-auth', + component: Layout, + hidden: true, + permissions: ['system:role:edit'], + children: [ + { + path: 'user/:roleId(\\d+)', + component: () => import('@/views/system/role/authUser'), + name: 'AuthUser', + meta: { title: '分配用户', activeMenu: '/system/role' } + } + ] + }, + { + path: '/system/dict-data', + component: Layout, + hidden: true, + permissions: ['system:dict:list'], + children: [ + { + path: 'index/:dictId(\\d+)', + component: () => import('@/views/system/dict/data'), + name: 'Data', + meta: { title: '字典数据', activeMenu: '/system/dict' } + } + ] + }, + { + path: '/monitor/job-log', + component: Layout, + hidden: true, + permissions: ['monitor:job:list'], + children: [ + { + path: 'index/:jobId(\\d+)', + component: () => import('@/views/monitor/job/log'), + name: 'JobLog', + meta: { title: '调度日志', activeMenu: '/monitor/job' } + } + ] + }, + { + path: '/tool/gen-edit', + component: Layout, + hidden: true, + permissions: ['tool:gen:edit'], + children: [ + { + path: 'index/:tableId(\\d+)', + component: () => import('@/views/tool/gen/editTable'), + name: 'GenEdit', + meta: { title: '修改生成配置', activeMenu: '/tool/gen' } + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(), + routes: constantRoutes, + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { top: 0 } + } + }, +}); + +export default router; \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/settings.js b/yanzhu-ui-vue3/src/settings.js new file mode 100644 index 00000000..10e1db41 --- /dev/null +++ b/yanzhu-ui-vue3/src/settings.js @@ -0,0 +1,47 @@ +export default { + /** + * 网页标题 + */ + title: import.meta.env.VITE_APP_TITLE, + /** + * 侧边栏主题 深色主题theme-dark,浅色主题theme-light + */ + sideTheme: 'theme-dark', + /** + * 是否系统布局配置 + */ + showSettings: false, + + /** + * 是否显示顶部导航 + */ + topNav: false, + + /** + * 是否显示 tagsView + */ + tagsView: true, + + /** + * 是否固定头部 + */ + fixedHeader: false, + + /** + * 是否显示logo + */ + sidebarLogo: true, + + /** + * 是否显示动态标题 + */ + dynamicTitle: false, + + /** + * @type {string | array} 'production' | ['production', 'development'] + * @description Need show err logs component. + * The default is only used in the production env + * If you want to also use it in dev, you can pass ['production', 'development'] + */ + errorLog: 'production' +} diff --git a/yanzhu-ui-vue3/src/store/index.js b/yanzhu-ui-vue3/src/store/index.js new file mode 100644 index 00000000..f10f3895 --- /dev/null +++ b/yanzhu-ui-vue3/src/store/index.js @@ -0,0 +1,3 @@ +const store = createPinia() + +export default store \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/store/modules/app.js b/yanzhu-ui-vue3/src/store/modules/app.js new file mode 100644 index 00000000..0b571596 --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/app.js @@ -0,0 +1,46 @@ +import Cookies from 'js-cookie' + +const useAppStore = defineStore( + 'app', + { + state: () => ({ + sidebar: { + opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, + withoutAnimation: false, + hide: false + }, + device: 'desktop', + size: Cookies.get('size') || 'default' + }), + actions: { + toggleSideBar(withoutAnimation) { + if (this.sidebar.hide) { + return false; + } + this.sidebar.opened = !this.sidebar.opened + this.sidebar.withoutAnimation = withoutAnimation + if (this.sidebar.opened) { + Cookies.set('sidebarStatus', 1) + } else { + Cookies.set('sidebarStatus', 0) + } + }, + closeSideBar({ withoutAnimation }) { + Cookies.set('sidebarStatus', 0) + this.sidebar.opened = false + this.sidebar.withoutAnimation = withoutAnimation + }, + toggleDevice(device) { + this.device = device + }, + setSize(size) { + this.size = size; + Cookies.set('size', size) + }, + toggleSideBarHide(status) { + this.sidebar.hide = status + } + } + }) + +export default useAppStore diff --git a/yanzhu-ui-vue3/src/store/modules/dict.js b/yanzhu-ui-vue3/src/store/modules/dict.js new file mode 100644 index 00000000..27fc3086 --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/dict.js @@ -0,0 +1,57 @@ +const useDictStore = defineStore( + 'dict', + { + state: () => ({ + dict: new Array() + }), + actions: { + // 获取字典 + getDict(_key) { + if (_key == null && _key == "") { + return null; + } + try { + for (let i = 0; i < this.dict.length; i++) { + if (this.dict[i].key == _key) { + return this.dict[i].value; + } + } + } catch (e) { + return null; + } + }, + // 设置字典 + setDict(_key, value) { + if (_key !== null && _key !== "") { + this.dict.push({ + key: _key, + value: value + }); + } + }, + // 删除字典 + removeDict(_key) { + var bln = false; + try { + for (let i = 0; i < this.dict.length; i++) { + if (this.dict[i].key == _key) { + this.dict.splice(i, 1); + return true; + } + } + } catch (e) { + bln = false; + } + return bln; + }, + // 清空字典 + cleanDict() { + this.dict = new Array(); + }, + // 初始字典 + initDict() { + } + } + }) + +export default useDictStore diff --git a/yanzhu-ui-vue3/src/store/modules/permission.js b/yanzhu-ui-vue3/src/store/modules/permission.js new file mode 100644 index 00000000..ef506e9b --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/permission.js @@ -0,0 +1,138 @@ +import auth from '@/plugins/auth' +import router, { constantRoutes, dynamicRoutes } from '@/router' +import { getRouters } from '@/api/menu' +import Layout from '@/layout/index' +import ParentView from '@/components/ParentView' +import InnerLink from '@/layout/components/InnerLink' + +// 匹配views里面所有的.vue文件 +const modules = import.meta.glob('./../../views/**/*.vue') + +const usePermissionStore = defineStore( + 'permission', + { + state: () => ({ + routes: [], + addRoutes: [], + defaultRoutes: [], + topbarRouters: [], + sidebarRouters: [] + }), + actions: { + setRoutes(routes) { + this.addRoutes = routes + this.routes = constantRoutes.concat(routes) + }, + setDefaultRoutes(routes) { + this.defaultRoutes = constantRoutes.concat(routes) + }, + setTopbarRoutes(routes) { + this.topbarRouters = routes + }, + setSidebarRouters(routes) { + this.sidebarRouters = routes + }, + generateRoutes(roles) { + return new Promise(resolve => { + // 向后端请求路由数据 + getRouters().then(res => { + const sdata = JSON.parse(JSON.stringify(res.data)) + const rdata = JSON.parse(JSON.stringify(res.data)) + const defaultData = JSON.parse(JSON.stringify(res.data)) + const sidebarRoutes = filterAsyncRouter(sdata) + const rewriteRoutes = filterAsyncRouter(rdata, false, true) + const defaultRoutes = filterAsyncRouter(defaultData) + const asyncRoutes = filterDynamicRoutes(dynamicRoutes) + asyncRoutes.forEach(route => { router.addRoute(route) }) + this.setRoutes(rewriteRoutes) + this.setSidebarRouters(constantRoutes.concat(sidebarRoutes)) + this.setDefaultRoutes(sidebarRoutes) + this.setTopbarRoutes(defaultRoutes) + resolve(rewriteRoutes) + }) + }) + } + } + }) + +// 遍历后台传来的路由字符串,转换为组件对象 +function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { + return asyncRouterMap.filter(route => { + if (type && route.children) { + route.children = filterChildren(route.children) + } + if (route.component) { + // Layout ParentView 组件特殊处理 + if (route.component === 'Layout') { + route.component = Layout + } else if (route.component === 'ParentView') { + route.component = ParentView + } else if (route.component === 'InnerLink') { + route.component = InnerLink + } else { + route.component = loadView(route.component) + } + } + if (route.children != null && route.children && route.children.length) { + route.children = filterAsyncRouter(route.children, route, type) + } else { + delete route['children'] + delete route['redirect'] + } + return true + }) +} + +function filterChildren(childrenMap, lastRouter = false) { + var children = [] + childrenMap.forEach((el, index) => { + if (el.children && el.children.length) { + if (el.component === 'ParentView' && !lastRouter) { + el.children.forEach(c => { + c.path = el.path + '/' + c.path + if (c.children && c.children.length) { + children = children.concat(filterChildren(c.children, c)) + return + } + children.push(c) + }) + return + } + } + if (lastRouter) { + el.path = lastRouter.path + '/' + el.path + } + children = children.concat(el) + }) + return children +} + +// 动态路由遍历,验证是否具备权限 +export function filterDynamicRoutes(routes) { + const res = [] + routes.forEach(route => { + if (route.permissions) { + if (auth.hasPermiOr(route.permissions)) { + res.push(route) + } + } else if (route.roles) { + if (auth.hasRoleOr(route.roles)) { + res.push(route) + } + } + }) + return res +} + +export const loadView = (view) => { + let res; + for (const path in modules) { + const dir = path.split('views/')[1].split('.vue')[0]; + if (dir === view) { + res = () => modules[path](); + } + } + return res; +} + +export default usePermissionStore diff --git a/yanzhu-ui-vue3/src/store/modules/settings.js b/yanzhu-ui-vue3/src/store/modules/settings.js new file mode 100644 index 00000000..22b73366 --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/settings.js @@ -0,0 +1,38 @@ +import defaultSettings from '@/settings' +import { useDynamicTitle } from '@/utils/dynamicTitle' + +const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' + +const useSettingsStore = defineStore( + 'settings', + { + state: () => ({ + title: '', + theme: storageSetting.theme || '#409EFF', + sideTheme: storageSetting.sideTheme || sideTheme, + showSettings: showSettings, + topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, + fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, + sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, + dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle + }), + actions: { + // 修改布局设置 + changeSetting(data) { + const { key, value } = data + if (this.hasOwnProperty(key)) { + this[key] = value + } + }, + // 设置网页标题 + setTitle(title) { + this.title = title + useDynamicTitle(); + } + } + }) + +export default useSettingsStore diff --git a/yanzhu-ui-vue3/src/store/modules/tagsView.js b/yanzhu-ui-vue3/src/store/modules/tagsView.js new file mode 100644 index 00000000..9d07f33d --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/tagsView.js @@ -0,0 +1,182 @@ +const useTagsViewStore = defineStore( + 'tags-view', + { + state: () => ({ + visitedViews: [], + cachedViews: [], + iframeViews: [] + }), + actions: { + addView(view) { + this.addVisitedView(view) + this.addCachedView(view) + }, + addIframeView(view) { + if (this.iframeViews.some(v => v.path === view.path)) return + this.iframeViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + addVisitedView(view) { + if (this.visitedViews.some(v => v.path === view.path)) return + this.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + addCachedView(view) { + if (this.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + this.cachedViews.push(view.name) + } + }, + delView(view) { + return new Promise(resolve => { + this.delVisitedView(view) + this.delCachedView(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delVisitedView(view) { + return new Promise(resolve => { + for (const [i, v] of this.visitedViews.entries()) { + if (v.path === view.path) { + this.visitedViews.splice(i, 1) + break + } + } + this.iframeViews = this.iframeViews.filter(item => item.path !== view.path) + resolve([...this.visitedViews]) + }) + }, + delIframeView(view) { + return new Promise(resolve => { + this.iframeViews = this.iframeViews.filter(item => item.path !== view.path) + resolve([...this.iframeViews]) + }) + }, + delCachedView(view) { + return new Promise(resolve => { + const index = this.cachedViews.indexOf(view.name) + index > -1 && this.cachedViews.splice(index, 1) + resolve([...this.cachedViews]) + }) + }, + delOthersViews(view) { + return new Promise(resolve => { + this.delOthersVisitedViews(view) + this.delOthersCachedViews(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delOthersVisitedViews(view) { + return new Promise(resolve => { + this.visitedViews = this.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + this.iframeViews = this.iframeViews.filter(item => item.path === view.path) + resolve([...this.visitedViews]) + }) + }, + delOthersCachedViews(view) { + return new Promise(resolve => { + const index = this.cachedViews.indexOf(view.name) + if (index > -1) { + this.cachedViews = this.cachedViews.slice(index, index + 1) + } else { + this.cachedViews = [] + } + resolve([...this.cachedViews]) + }) + }, + delAllViews(view) { + return new Promise(resolve => { + this.delAllVisitedViews(view) + this.delAllCachedViews(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delAllVisitedViews(view) { + return new Promise(resolve => { + const affixTags = this.visitedViews.filter(tag => tag.meta.affix) + this.visitedViews = affixTags + this.iframeViews = [] + resolve([...this.visitedViews]) + }) + }, + delAllCachedViews(view) { + return new Promise(resolve => { + this.cachedViews = [] + resolve([...this.cachedViews]) + }) + }, + updateVisitedView(view) { + for (let v of this.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + delRightTags(view) { + return new Promise(resolve => { + const index = this.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + this.visitedViews = this.visitedViews.filter((item, idx) => { + if (idx <= index || (item.meta && item.meta.affix)) { + return true + } + const i = this.cachedViews.indexOf(item.name) + if (i > -1) { + this.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = this.iframeViews.findIndex(v => v.path === item.path) + this.iframeViews.splice(fi, 1) + } + return false + }) + resolve([...this.visitedViews]) + }) + }, + delLeftTags(view) { + return new Promise(resolve => { + const index = this.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + this.visitedViews = this.visitedViews.filter((item, idx) => { + if (idx >= index || (item.meta && item.meta.affix)) { + return true + } + const i = this.cachedViews.indexOf(item.name) + if (i > -1) { + this.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = this.iframeViews.findIndex(v => v.path === item.path) + this.iframeViews.splice(fi, 1) + } + return false + }) + resolve([...this.visitedViews]) + }) + } + } + }) + +export default useTagsViewStore diff --git a/yanzhu-ui-vue3/src/store/modules/user.js b/yanzhu-ui-vue3/src/store/modules/user.js new file mode 100644 index 00000000..e7a4301b --- /dev/null +++ b/yanzhu-ui-vue3/src/store/modules/user.js @@ -0,0 +1,71 @@ +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/utils/auth' +import defAva from '@/assets/images/profile.jpg' + +const useUserStore = defineStore( + 'user', + { + state: () => ({ + token: getToken(), + name: '', + avatar: '', + roles: [], + permissions: [] + }), + actions: { + // 登录 + login(userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + let data = res.data + setToken(data.access_token) + this.token = data.access_token + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + // 获取用户信息 + getInfo() { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.user + const avatar = (user.avatar == "" || user.avatar == null) ? defAva : user.avatar; + + if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + this.roles = res.roles + this.permissions = res.permissions + } else { + this.roles = ['ROLE_DEFAULT'] + } + this.name = user.userName + this.avatar = avatar; + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + // 退出系统 + logOut() { + return new Promise((resolve, reject) => { + logout(this.token).then(() => { + this.token = '' + this.roles = [] + this.permissions = [] + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + } + } + }) + +export default useUserStore diff --git a/yanzhu-ui-vue3/src/utils/auth.js b/yanzhu-ui-vue3/src/utils/auth.js new file mode 100644 index 00000000..a673d227 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/auth.js @@ -0,0 +1,29 @@ +import Cookies from 'js-cookie' + +const TokenKey = 'Admin-Token' + +const ExpiresInKey = 'Admin-Expires-In' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} + +export function getExpiresIn() { + return Cookies.get(ExpiresInKey) || -1 +} + +export function setExpiresIn(time) { + return Cookies.set(ExpiresInKey, time) +} + +export function removeExpiresIn() { + return Cookies.remove(ExpiresInKey) +} diff --git a/yanzhu-ui-vue3/src/utils/dict.js b/yanzhu-ui-vue3/src/utils/dict.js new file mode 100644 index 00000000..9648f149 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/dict.js @@ -0,0 +1,24 @@ +import useDictStore from '@/store/modules/dict' +import { getDicts } from '@/api/system/dict/data' + +/** + * 获取字典数据 + */ +export function useDict(...args) { + const res = ref({}); + return (() => { + args.forEach((dictType, index) => { + res.value[dictType] = []; + const dicts = useDictStore().getDict(dictType); + if (dicts) { + res.value[dictType] = dicts; + } else { + getDicts(dictType).then(resp => { + res.value[dictType] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass })) + useDictStore().setDict(dictType, res.value[dictType]); + }) + } + }) + return toRefs(res.value); + })() +} \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/utils/dynamicTitle.js b/yanzhu-ui-vue3/src/utils/dynamicTitle.js new file mode 100644 index 00000000..64404b20 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/dynamicTitle.js @@ -0,0 +1,15 @@ +import store from '@/store' +import defaultSettings from '@/settings' +import useSettingsStore from '@/store/modules/settings' + +/** + * 动态修改标题 + */ +export function useDynamicTitle() { + const settingsStore = useSettingsStore(); + if (settingsStore.dynamicTitle) { + document.title = settingsStore.title + ' - ' + defaultSettings.title; + } else { + document.title = defaultSettings.title; + } +} \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/utils/errorCode.js b/yanzhu-ui-vue3/src/utils/errorCode.js new file mode 100644 index 00000000..d2111ee1 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/yanzhu-ui-vue3/src/utils/index.js b/yanzhu-ui-vue3/src/utils/index.js new file mode 100644 index 00000000..4e65504c --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/index.js @@ -0,0 +1,390 @@ +import { parseTime } from './ruoyi' + +/** + * 表格时间格式化 + */ +export function formatDate(cellValue) { + if (cellValue == null || cellValue == "") return ""; + var date = new Date(cellValue) + var year = date.getFullYear() + var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 + var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() + var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() + var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() + var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() + return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return ( + d.getMonth() + + 1 + + '月' + + d.getDate() + + '日' + + d.getHours() + + '时' + + d.getMinutes() + + '分' + ) + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function getQueryObject(url) { + url = url == null ? window.location.href : url + const search = url.substring(url.lastIndexOf('?') + 1) + const obj = {} + const reg = /([^?&=]+)=([^?&=]*)/g + search.replace(reg, (rs, $1, $2) => { + const name = decodeURIComponent($1) + let val = decodeURIComponent($2) + val = String(val) + obj[name] = val + return rs + }) + return obj +} + +/** + * @param {string} input value + * @returns {number} output value + */ +export function byteLength(str) { + // returns the byte length of an utf8 string + let s = str.length + for (var i = str.length - 1; i >= 0; i--) { + const code = str.charCodeAt(i) + if (code > 0x7f && code <= 0x7ff) s++ + else if (code > 0x7ff && code <= 0xffff) s += 2 + if (code >= 0xDC00 && code <= 0xDFFF) i-- + } + return s +} + +/** + * @param {Array} actual + * @returns {Array} + */ +export function cleanArray(actual) { + const newArray = [] + for (let i = 0; i < actual.length; i++) { + if (actual[i]) { + newArray.push(actual[i]) + } + } + return newArray +} + +/** + * @param {Object} json + * @returns {Array} + */ +export function param(json) { + if (!json) return '' + return cleanArray( + Object.keys(json).map(key => { + if (json[key] === undefined) return '' + return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) + }) + ).join('&') +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +/** + * @param {string} val + * @returns {string} + */ +export function html2Text(val) { + const div = document.createElement('div') + div.innerHTML = val + return div.textContent || div.innerText +} + +/** + * Merges two objects, giving the last one precedence + * @param {Object} target + * @param {(Object|Array)} source + * @returns {Object} + */ +export function objectMerge(target, source) { + if (typeof target !== 'object') { + target = {} + } + if (Array.isArray(source)) { + return source.slice() + } + Object.keys(source).forEach(property => { + const sourceProperty = source[property] + if (typeof sourceProperty === 'object') { + target[property] = objectMerge(target[property], sourceProperty) + } else { + target[property] = sourceProperty + } + }) + return target +} + +/** + * @param {HTMLElement} element + * @param {string} className + */ +export function toggleClass(element, className) { + if (!element || !className) { + return + } + let classString = element.className + const nameIndex = classString.indexOf(className) + if (nameIndex === -1) { + classString += '' + className + } else { + classString = + classString.substr(0, nameIndex) + + classString.substr(nameIndex + className.length) + } + element.className = classString +} + +/** + * @param {string} type + * @returns {Date} + */ +export function getTime(type) { + if (type === 'start') { + return new Date().getTime() - 3600 * 1000 * 24 * 90 + } else { + return new Date(new Date().toDateString()) + } +} + +/** + * @param {Function} func + * @param {number} wait + * @param {boolean} immediate + * @return {*} + */ +export function debounce(func, wait, immediate) { + let timeout, args, context, timestamp, result + + const later = function() { + // 据上一次触发时间间隔 + const last = +new Date() - timestamp + + // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait + if (last < wait && last > 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = null + // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 + if (!immediate) { + result = func.apply(context, args) + if (!timeout) context = args = null + } + } + } + + return function(...args) { + context = this + timestamp = +new Date() + const callNow = immediate && !timeout + // 如果延时不存在,重新设定延时 + if (!timeout) timeout = setTimeout(later, wait) + if (callNow) { + result = func.apply(context, args) + context = args = null + } + + return result + } +} + +/** + * This is just a simple version of deep copy + * Has a lot of edge cases bug + * If you want to use a perfect deep copy, use lodash's _.cloneDeep + * @param {Object} source + * @returns {Object} + */ +export function deepClone(source) { + if (!source && typeof source !== 'object') { + throw new Error('error arguments', 'deepClone') + } + const targetObj = source.constructor === Array ? [] : {} + Object.keys(source).forEach(keys => { + if (source[keys] && typeof source[keys] === 'object') { + targetObj[keys] = deepClone(source[keys]) + } else { + targetObj[keys] = source[keys] + } + }) + return targetObj +} + +/** + * @param {Array} arr + * @returns {Array} + */ +export function uniqueArr(arr) { + return Array.from(new Set(arr)) +} + +/** + * @returns {string} + */ +export function createUniqueString() { + const timestamp = +new Date() + '' + const randomNum = parseInt((1 + Math.random()) * 65536) + '' + return (+(randomNum + timestamp)).toString(32) +} + +/** + * Check if an element has a class + * @param {HTMLElement} elm + * @param {string} cls + * @returns {boolean} + */ +export function hasClass(ele, cls) { + return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) +} + +/** + * Add class to element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function addClass(ele, cls) { + if (!hasClass(ele, cls)) ele.className += ' ' + cls +} + +/** + * Remove class from element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function removeClass(ele, cls) { + if (hasClass(ele, cls)) { + const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') + ele.className = ele.className.replace(reg, ' ') + } +} + +export function makeMap(str, expectsLowerCase) { + const map = Object.create(null) + const list = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase + ? val => map[val.toLowerCase()] + : val => map[val] +} + +export const exportDefault = 'export default ' + +export const beautifierConf = { + html: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'separate', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: false, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + }, + js: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'normal', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: true, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + } +} + +// 首字母大小 +export function titleCase(str) { + return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) +} + +// 下划转驼峰 +export function camelCase(str) { + return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase()) +} + +export function isNumberStr(str) { + return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) +} + diff --git a/yanzhu-ui-vue3/src/utils/jsencrypt.js b/yanzhu-ui-vue3/src/utils/jsencrypt.js new file mode 100644 index 00000000..78d95234 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/jsencrypt.js @@ -0,0 +1,30 @@ +import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' + +// 密钥对生成 http://web.chacuo.net/netrsakeypair + +const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' + +const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + + 'UP8iWi1Qw0Y=' + +// 加密 +export function encrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPublicKey(publicKey) // 设置公钥 + return encryptor.encrypt(txt) // 对数据进行加密 +} + +// 解密 +export function decrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPrivateKey(privateKey) // 设置私钥 + return encryptor.decrypt(txt) // 对数据进行解密 +} + diff --git a/yanzhu-ui-vue3/src/utils/permission.js b/yanzhu-ui-vue3/src/utils/permission.js new file mode 100644 index 00000000..93fee87f --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/permission.js @@ -0,0 +1,51 @@ +import useUserStore from '@/store/modules/user' + +/** + * 字符权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkPermi(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = useUserStore().permissions + const permissionDatas = value + const all_permission = "*:*:*"; + + const hasPermission = permissions.some(permission => { + return all_permission === permission || permissionDatas.includes(permission) + }) + + if (!hasPermission) { + return false + } + return true + } else { + console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) + return false + } +} + +/** + * 角色权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkRole(value) { + if (value && value instanceof Array && value.length > 0) { + const roles = useUserStore().roles + const permissionRoles = value + const super_admin = "admin"; + + const hasRole = roles.some(role => { + return super_admin === role || permissionRoles.includes(role) + }) + + if (!hasRole) { + return false + } + return true + } else { + console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } +} \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/utils/request.js b/yanzhu-ui-vue3/src/utils/request.js new file mode 100644 index 00000000..e0d72280 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/request.js @@ -0,0 +1,146 @@ +import axios from 'axios' +import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { tansParams, blobValidate } from '@/utils/ruoyi' +import cache from '@/plugins/cache' +import { saveAs } from 'file-saver' +import useUserStore from '@/store/modules/user' + +let downloadLoadingInstance; +// 是否显示重新登录 +export let isRelogin = { show: false }; + +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +// 创建axios实例 +const service = axios.create({ + // axios中请求配置有baseURL选项,表示请求URL公共部分 + baseURL: import.meta.env.VITE_APP_BASE_API, + // 超时 + timeout: 10000 +}) + +// request拦截器 +service.interceptors.request.use(config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false + if (getToken() && !isToken) { + config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + } + // get请求映射params参数 + if (config.method === 'get' && config.params) { + let url = config.url + '?' + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const sessionObj = cache.session.getJSON('sessionObj') + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + cache.session.setJSON('sessionObj', requestObj) + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '数据正在处理,请勿重复提交'; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + cache.session.setJSON('sessionObj', requestObj) + } + } + } + return config +}, error => { + console.log(error) + Promise.reject(error) +}) + +// 响应拦截器 +service.interceptors.response.use(res => { + // 未设置状态码则默认成功状态 + const code = res.data.code || 200; + // 获取错误信息 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + // 二进制数据则直接返回 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { + return res.data + } + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { + isRelogin.show = false; + useUserStore().logOut().then(() => { + location.href = '/index'; + }) + }).catch(() => { + isRelogin.show = false; + }); + } + return Promise.reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + ElMessage({ message: msg, type: 'error' }) + return Promise.reject(new Error(msg)) + } else if (code === 601) { + ElMessage({ message: msg, type: 'warning' }) + return Promise.reject(new Error(msg)) + } else if (code !== 200) { + ElNotification.error({ title: msg }) + return Promise.reject('error') + } else { + return Promise.resolve(res.data) + } + }, + error => { + console.log('err' + error) + let { message } = error; + if (message == "Network Error") { + message = "后端接口连接异常"; + } else if (message.includes("timeout")) { + message = "系统接口请求超时"; + } else if (message.includes("Request failed with status code")) { + message = "系统接口" + message.substr(message.length - 3) + "异常"; + } + ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) + return Promise.reject(error) + } +) + +// 通用下载方法 +export function download(url, params, filename, config) { + downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", }) + return service.post(url, params, { + transformRequest: [(params) => { return tansParams(params) }], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob', + ...config + }).then(async (data) => { + const isBlob = blobValidate(data); + if (isBlob) { + const blob = new Blob([data]) + saveAs(blob, filename) + } else { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + ElMessage.error(errMsg); + } + downloadLoadingInstance.close(); + }).catch((r) => { + console.error(r) + ElMessage.error('下载文件出现错误,请联系管理员!') + downloadLoadingInstance.close(); + }) +} + +export default service diff --git a/yanzhu-ui-vue3/src/utils/ruoyi.js b/yanzhu-ui-vue3/src/utils/ruoyi.js new file mode 100644 index 00000000..4efca08f --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/ruoyi.js @@ -0,0 +1,246 @@ + + +/** + * 通用js方法封装处理 + * Copyright (c) 2019 ruoyi + */ + +// 日期格式化 +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +// 表单重置 +export function resetForm(refName) { + if (this.$refs[refName]) { + this.$refs[refName].resetFields(); + } +} + +// 添加日期范围 +export function addDateRange(params, dateRange, propName) { + let search = params; + search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}; + dateRange = Array.isArray(dateRange) ? dateRange : []; + if (typeof (propName) === 'undefined') { + search.params['beginTime'] = dateRange[0]; + search.params['endTime'] = dateRange[1]; + } else { + search.params['begin' + propName] = dateRange[0]; + search.params['end' + propName] = dateRange[1]; + } + return search; +} + +// 回显数据字典 +export function selectDictLabel(datas, value) { + if (value === undefined) { + return ""; + } + var actions = []; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + value)) { + actions.push(datas[key].label); + return true; + } + }) + if (actions.length === 0) { + actions.push(value); + } + return actions.join(''); +} + +// 回显数据字典(字符串数组) +export function selectDictLabels(datas, value, separator) { + if (value === undefined || value.length ===0) { + return ""; + } + if (Array.isArray(value)) { + value = value.join(","); + } + var actions = []; + var currentSeparator = undefined === separator ? "," : separator; + var temp = value.split(currentSeparator); + Object.keys(value.split(currentSeparator)).some((val) => { + var match = false; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + temp[val])) { + actions.push(datas[key].label + currentSeparator); + match = true; + } + }) + if (!match) { + actions.push(temp[val] + currentSeparator); + } + }) + return actions.join('').substring(0, actions.join('').length - 1); +} + +// 字符串格式化(%s ) +export function sprintf(str) { + var args = arguments, flag = true, i = 1; + str = str.replace(/%s/g, function () { + var arg = args[i++]; + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; +} + +// 转换字符串,undefined,null等转化为"" +export function parseStrEmpty(str) { + if (!str || str == "undefined" || str == "null") { + return ""; + } + return str; +} + +// 数据合并 +export function mergeRecursive(source, target) { + for (var p in target) { + try { + if (target[p].constructor == Object) { + source[p] = mergeRecursive(source[p], target[p]); + } else { + source[p] = target[p]; + } + } catch (e) { + source[p] = target[p]; + } + } + return source; +}; + +/** + * 构造树型结构数据 + * @param {*} data 数据源 + * @param {*} id id字段 默认 'id' + * @param {*} parentId 父节点字段 默认 'parentId' + * @param {*} children 孩子节点字段 默认 'children' + */ +export function handleTree(data, id, parentId, children) { + let config = { + id: id || 'id', + parentId: parentId || 'parentId', + childrenList: children || 'children' + }; + + var childrenListMap = {}; + var nodeIds = {}; + var tree = []; + + for (let d of data) { + let parentId = d[config.parentId]; + if (childrenListMap[parentId] == null) { + childrenListMap[parentId] = []; + } + nodeIds[d[config.id]] = d; + childrenListMap[parentId].push(d); + } + + for (let d of data) { + let parentId = d[config.parentId]; + if (nodeIds[parentId] == null) { + tree.push(d); + } + } + + for (let t of tree) { + adaptToChildrenList(t); + } + + function adaptToChildrenList(o) { + if (childrenListMap[o[config.id]] !== null) { + o[config.childrenList] = childrenListMap[o[config.id]]; + } + if (o[config.childrenList]) { + for (let c of o[config.childrenList]) { + adaptToChildrenList(c); + } + } + } + return tree; +} + +/** +* 参数处理 +* @param {*} params 参数 +*/ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName]; + var part = encodeURIComponent(propName) + "="; + if (value !== null && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']'; + var subPart = encodeURIComponent(params) + "="; + result += subPart + encodeURIComponent(value[key]) + "&"; + } + } + } else { + result += part + encodeURIComponent(value) + "&"; + } + } + } + return result +} + + +// 返回项目路径 +export function getNormalPath(p) { + if (p.length === 0 || !p || p == 'undefined') { + return p + }; + let res = p.replace('//', '/') + if (res[res.length - 1] === '/') { + return res.slice(0, res.length - 1) + } + return res; +} + +// 验证是否为blob格式 +export function blobValidate(data) { + return data.type !== 'application/json' +} diff --git a/yanzhu-ui-vue3/src/utils/scroll-to.js b/yanzhu-ui-vue3/src/utils/scroll-to.js new file mode 100644 index 00000000..c5d8e04e --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/scroll-to.js @@ -0,0 +1,58 @@ +Math.easeInOutQuad = function(t, b, c, d) { + t /= d / 2 + if (t < 1) { + return c / 2 * t * t + b + } + t-- + return -c / 2 * (t * (t - 2) - 1) + b +} + +// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts +var requestAnimFrame = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } +})() + +/** + * Because it's so fucking difficult to detect the scrolling element, just move them all + * @param {number} amount + */ +function move(amount) { + document.documentElement.scrollTop = amount + document.body.parentNode.scrollTop = amount + document.body.scrollTop = amount +} + +function position() { + return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop +} + +/** + * @param {number} to + * @param {number} duration + * @param {Function} callback + */ +export function scrollTo(to, duration, callback) { + const start = position() + const change = to - start + const increment = 20 + let currentTime = 0 + duration = (typeof (duration) === 'undefined') ? 500 : duration + var animateScroll = function() { + // increment the time + currentTime += increment + // find the value with the quadratic in-out easing function + var val = Math.easeInOutQuad(currentTime, start, change, duration) + // move the document.body + move(val) + // do the animation unless its over + if (currentTime < duration) { + requestAnimFrame(animateScroll) + } else { + if (callback && typeof (callback) === 'function') { + // the animation is done so lets callback + callback() + } + } + } + animateScroll() +} diff --git a/yanzhu-ui-vue3/src/utils/theme.js b/yanzhu-ui-vue3/src/utils/theme.js new file mode 100644 index 00000000..f4badc67 --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/theme.js @@ -0,0 +1,49 @@ +// 处理主题样式 +export function handleThemeStyle(theme) { + document.documentElement.style.setProperty('--el-color-primary', theme) + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(theme, i / 10)}`) + } + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, `${getDarkColor(theme, i / 10)}`) + } +} + +// hex颜色转rgb颜色 +export function hexToRgb(str) { + str = str.replace('#', '') + let hexs = str.match(/../g) + for (let i = 0; i < 3; i++) { + hexs[i] = parseInt(hexs[i], 16) + } + return hexs +} + +// rgb颜色转Hex颜色 +export function rgbToHex(r, g, b) { + let hexs = [r.toString(16), g.toString(16), b.toString(16)] + for (let i = 0; i < 3; i++) { + if (hexs[i].length == 1) { + hexs[i] = `0${hexs[i]}` + } + } + return `#${hexs.join('')}` +} + +// 变浅颜色值 +export function getLightColor(color, level) { + let rgb = hexToRgb(color) + for (let i = 0; i < 3; i++) { + rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]) + } + return rgbToHex(rgb[0], rgb[1], rgb[2]) +} + +// 变深颜色值 +export function getDarkColor(color, level) { + let rgb = hexToRgb(color) + for (let i = 0; i < 3; i++) { + rgb[i] = Math.floor(rgb[i] * (1 - level)) + } + return rgbToHex(rgb[0], rgb[1], rgb[2]) +} diff --git a/yanzhu-ui-vue3/src/utils/validate.js b/yanzhu-ui-vue3/src/utils/validate.js new file mode 100644 index 00000000..702add4b --- /dev/null +++ b/yanzhu-ui-vue3/src/utils/validate.js @@ -0,0 +1,93 @@ +/** + * 判断url是否是http或https + * @param {string} path + * @returns {Boolean} + */ + export function isHttp(url) { + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 +} + +/** + * 判断path是否为外链 + * @param {string} path + * @returns {Boolean} + */ + export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/** + * @param {string} url + * @returns {Boolean} + */ +export function validURL(url) { + const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} + +/** + * @param {string} email + * @returns {Boolean} + */ +export function validEmail(email) { + const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return reg.test(email) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function isString(str) { + if (typeof str === 'string' || str instanceof String) { + return true + } + return false +} + +/** + * @param {Array} arg + * @returns {Boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} diff --git a/yanzhu-ui-vue3/src/views/error/401.vue b/yanzhu-ui-vue3/src/views/error/401.vue new file mode 100644 index 00000000..1ba37922 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/error/401.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/yanzhu-ui-vue3/src/views/error/404.vue b/yanzhu-ui-vue3/src/views/error/404.vue new file mode 100644 index 00000000..f2053032 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/error/404.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/yanzhu-ui-vue3/src/views/index.vue b/yanzhu-ui-vue3/src/views/index.vue new file mode 100644 index 00000000..8c1bf417 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/index.vue @@ -0,0 +1,911 @@ + + + + + + diff --git a/yanzhu-ui-vue3/src/views/login.vue b/yanzhu-ui-vue3/src/views/login.vue new file mode 100644 index 00000000..c2bb42d1 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/login.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/yanzhu-ui-vue3/src/views/monitor/job/index.vue b/yanzhu-ui-vue3/src/views/monitor/job/index.vue new file mode 100644 index 00000000..fd702233 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/monitor/job/index.vue @@ -0,0 +1,483 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/monitor/job/log.vue b/yanzhu-ui-vue3/src/views/monitor/job/log.vue new file mode 100644 index 00000000..f71a501f --- /dev/null +++ b/yanzhu-ui-vue3/src/views/monitor/job/log.vue @@ -0,0 +1,277 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/monitor/online/index.vue b/yanzhu-ui-vue3/src/views/monitor/online/index.vue new file mode 100644 index 00000000..9af1eee6 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/monitor/online/index.vue @@ -0,0 +1,102 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/redirect/index.vue b/yanzhu-ui-vue3/src/views/redirect/index.vue new file mode 100644 index 00000000..a469960d --- /dev/null +++ b/yanzhu-ui-vue3/src/views/redirect/index.vue @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/views/register.vue b/yanzhu-ui-vue3/src/views/register.vue new file mode 100644 index 00000000..64aea639 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/register.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/yanzhu-ui-vue3/src/views/system/area/index.vue b/yanzhu-ui-vue3/src/views/system/area/index.vue new file mode 100644 index 00000000..d6d8716a --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/area/index.vue @@ -0,0 +1,319 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/config/index.vue b/yanzhu-ui-vue3/src/views/system/config/index.vue new file mode 100644 index 00000000..34fd53da --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/config/index.vue @@ -0,0 +1,305 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/dept/index.vue b/yanzhu-ui-vue3/src/views/system/dept/index.vue new file mode 100644 index 00000000..d073a261 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/dept/index.vue @@ -0,0 +1,274 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/dict/data.vue b/yanzhu-ui-vue3/src/views/system/dict/data.vue new file mode 100644 index 00000000..b900666d --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/dict/data.vue @@ -0,0 +1,350 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/dict/index.vue b/yanzhu-ui-vue3/src/views/system/dict/index.vue new file mode 100644 index 00000000..297ac84f --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/dict/index.vue @@ -0,0 +1,312 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/logininfor/index.vue b/yanzhu-ui-vue3/src/views/system/logininfor/index.vue new file mode 100644 index 00000000..0d0a9008 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/logininfor/index.vue @@ -0,0 +1,221 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/menu/index.vue b/yanzhu-ui-vue3/src/views/system/menu/index.vue new file mode 100644 index 00000000..cf53ac90 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/menu/index.vue @@ -0,0 +1,441 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/notice/index.vue b/yanzhu-ui-vue3/src/views/system/notice/index.vue new file mode 100644 index 00000000..c26b8c40 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/notice/index.vue @@ -0,0 +1,283 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/operlog/index.vue b/yanzhu-ui-vue3/src/views/system/operlog/index.vue new file mode 100644 index 00000000..040835ab --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/operlog/index.vue @@ -0,0 +1,292 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/post/index.vue b/yanzhu-ui-vue3/src/views/system/post/index.vue new file mode 100644 index 00000000..6fd1b641 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/post/index.vue @@ -0,0 +1,277 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/role/authUser.vue b/yanzhu-ui-vue3/src/views/system/role/authUser.vue new file mode 100644 index 00000000..66b5f5e6 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/role/authUser.vue @@ -0,0 +1,172 @@ + + + + diff --git a/yanzhu-ui-vue3/src/views/system/role/index.vue b/yanzhu-ui-vue3/src/views/system/role/index.vue new file mode 100644 index 00000000..65c82160 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/role/index.vue @@ -0,0 +1,559 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/role/selectUser.vue b/yanzhu-ui-vue3/src/views/system/role/selectUser.vue new file mode 100644 index 00000000..9be1ec96 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/role/selectUser.vue @@ -0,0 +1,140 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/user/authRole.vue b/yanzhu-ui-vue3/src/views/system/user/authRole.vue new file mode 100644 index 00000000..0b5c14bc --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/authRole.vue @@ -0,0 +1,112 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/user/index.vue b/yanzhu-ui-vue3/src/views/system/user/index.vue new file mode 100644 index 00000000..d6cfdd61 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/index.vue @@ -0,0 +1,607 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/user/profile/index.vue b/yanzhu-ui-vue3/src/views/system/user/profile/index.vue new file mode 100644 index 00000000..9ef98407 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/profile/index.vue @@ -0,0 +1,87 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/user/profile/resetPwd.vue b/yanzhu-ui-vue3/src/views/system/user/profile/resetPwd.vue new file mode 100644 index 00000000..dec2d79c --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/profile/resetPwd.vue @@ -0,0 +1,57 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/system/user/profile/userAvatar.vue b/yanzhu-ui-vue3/src/views/system/user/profile/userAvatar.vue new file mode 100644 index 00000000..0878f32f --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/profile/userAvatar.vue @@ -0,0 +1,169 @@ + + + + + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/views/system/user/profile/userInfo.vue b/yanzhu-ui-vue3/src/views/system/user/profile/userInfo.vue new file mode 100644 index 00000000..2d62c842 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/system/user/profile/userInfo.vue @@ -0,0 +1,56 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/tool/build/index.vue b/yanzhu-ui-vue3/src/views/tool/build/index.vue new file mode 100644 index 00000000..c3543a92 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/build/index.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/yanzhu-ui-vue3/src/views/tool/gen/basicInfoForm.vue b/yanzhu-ui-vue3/src/views/tool/gen/basicInfoForm.vue new file mode 100644 index 00000000..39c85150 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/gen/basicInfoForm.vue @@ -0,0 +1,48 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/tool/gen/editTable.vue b/yanzhu-ui-vue3/src/views/tool/gen/editTable.vue new file mode 100644 index 00000000..ddcbfd5b --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/gen/editTable.vue @@ -0,0 +1,198 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/tool/gen/genInfoForm.vue b/yanzhu-ui-vue3/src/views/tool/gen/genInfoForm.vue new file mode 100644 index 00000000..2e28e262 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/gen/genInfoForm.vue @@ -0,0 +1,281 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/tool/gen/importTable.vue b/yanzhu-ui-vue3/src/views/tool/gen/importTable.vue new file mode 100644 index 00000000..33b56337 --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/gen/importTable.vue @@ -0,0 +1,118 @@ + + + diff --git a/yanzhu-ui-vue3/src/views/tool/gen/index.vue b/yanzhu-ui-vue3/src/views/tool/gen/index.vue new file mode 100644 index 00000000..bf8d12bf --- /dev/null +++ b/yanzhu-ui-vue3/src/views/tool/gen/index.vue @@ -0,0 +1,283 @@ + + + diff --git a/yanzhu-ui-vue3/vite.config.js b/yanzhu-ui-vue3/vite.config.js new file mode 100644 index 00000000..2b6f847c --- /dev/null +++ b/yanzhu-ui-vue3/vite.config.js @@ -0,0 +1,58 @@ +import { defineConfig, loadEnv } from 'vite' +import path from 'path' +import createVitePlugins from './vite/plugins' + +// https://vitejs.dev/config/ +export default defineConfig(({ mode, command }) => { + const env = loadEnv(mode, process.cwd()) + const { VITE_APP_ENV } = env + return { + // 部署生产环境和开发环境下的URL。 + // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上 + // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 + base: VITE_APP_ENV === 'production' ? '/' : '/', + plugins: createVitePlugins(env, command === 'build'), + resolve: { + // https://cn.vitejs.dev/config/#resolve-alias + alias: { + // 设置路径 + '~': path.resolve(__dirname, './'), + // 设置别名 + '@': path.resolve(__dirname, './src') + }, + // https://cn.vitejs.dev/config/#resolve-extensions + extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] + }, + // vite 相关配置 + server: { + port: 80, + host: true, + open: true, + proxy: { + // https://cn.vitejs.dev/config/#server-proxy + '/dev-api': { + target: 'http://localhost:8080', + changeOrigin: true, + rewrite: (p) => p.replace(/^\/dev-api/, '') + } + } + }, + //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file + css: { + postcss: { + plugins: [ + { + postcssPlugin: 'internal:charset-removal', + AtRule: { + charset: (atRule) => { + if (atRule.name === 'charset') { + atRule.remove(); + } + } + } + } + ] + } + } + } +}) diff --git a/yanzhu-ui-vue3/vite/plugins/auto-import.js b/yanzhu-ui-vue3/vite/plugins/auto-import.js new file mode 100644 index 00000000..a5d35763 --- /dev/null +++ b/yanzhu-ui-vue3/vite/plugins/auto-import.js @@ -0,0 +1,12 @@ +import autoImport from 'unplugin-auto-import/vite' + +export default function createAutoImport() { + return autoImport({ + imports: [ + 'vue', + 'vue-router', + 'pinia' + ], + dts: false + }) +} diff --git a/yanzhu-ui-vue3/vite/plugins/compression.js b/yanzhu-ui-vue3/vite/plugins/compression.js new file mode 100644 index 00000000..e90aaecc --- /dev/null +++ b/yanzhu-ui-vue3/vite/plugins/compression.js @@ -0,0 +1,28 @@ +import compression from 'vite-plugin-compression' + +export default function createCompression(env) { + const { VITE_BUILD_COMPRESS } = env + const plugin = [] + if (VITE_BUILD_COMPRESS) { + const compressList = VITE_BUILD_COMPRESS.split(',') + if (compressList.includes('gzip')) { + // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 + plugin.push( + compression({ + ext: '.gz', + deleteOriginFile: false + }) + ) + } + if (compressList.includes('brotli')) { + plugin.push( + compression({ + ext: '.br', + algorithm: 'brotliCompress', + deleteOriginFile: false + }) + ) + } + } + return plugin +} diff --git a/yanzhu-ui-vue3/vite/plugins/index.js b/yanzhu-ui-vue3/vite/plugins/index.js new file mode 100644 index 00000000..10e17c3d --- /dev/null +++ b/yanzhu-ui-vue3/vite/plugins/index.js @@ -0,0 +1,15 @@ +import vue from '@vitejs/plugin-vue' + +import createAutoImport from './auto-import' +import createSvgIcon from './svg-icon' +import createCompression from './compression' +import createSetupExtend from './setup-extend' + +export default function createVitePlugins(viteEnv, isBuild = false) { + const vitePlugins = [vue()] + vitePlugins.push(createAutoImport()) + vitePlugins.push(createSetupExtend()) + vitePlugins.push(createSvgIcon(isBuild)) + isBuild && vitePlugins.push(...createCompression(viteEnv)) + return vitePlugins +} diff --git a/yanzhu-ui-vue3/vite/plugins/setup-extend.js b/yanzhu-ui-vue3/vite/plugins/setup-extend.js new file mode 100644 index 00000000..a4980f30 --- /dev/null +++ b/yanzhu-ui-vue3/vite/plugins/setup-extend.js @@ -0,0 +1,5 @@ +import setupExtend from 'vite-plugin-vue-setup-extend' + +export default function createSetupExtend() { + return setupExtend() +} diff --git a/yanzhu-ui-vue3/vite/plugins/svg-icon.js b/yanzhu-ui-vue3/vite/plugins/svg-icon.js new file mode 100644 index 00000000..30a4140f --- /dev/null +++ b/yanzhu-ui-vue3/vite/plugins/svg-icon.js @@ -0,0 +1,10 @@ +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import path from 'path' + +export default function createSvgIcon(isBuild) { + return createSvgIconsPlugin({ + iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')], + symbolId: 'icon-[dir]-[name]', + svgoOptions: isBuild + }) +}

F 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�pkhw+1@vOeDE~Z< zHO~kl_H!sW&ZFuX!j|oOfhc-+Ri3SaTLWYXy&HBmRhyPIY3b4Bd$%kXq*YAkkT;zZ z@Mb7&<;NT7$CrW4Jg~PV%7~Ef!g4fCpicSsIqd_9lY z;~RK0IRS>25{`E)m#}L-kDBFs>}cmvv0aq5Wxa%Lz47moro5;M@P}H;Q1GY$A%KSD&?{9;wdse+`_BzAtbaBRQ(guuLybsdIBpw z-l|aWj$TuzB?un(|A60bYOy4WbxB4RB( zkNb$;zk{`a3t`77Dn7G#gZG>xQZ8%5a#{C=j*Eiyws{mg^iY~dQ4vTSkxE2BVm999gs5xzto67|@uiySl zmWaqJp%Dt1wONXXVmQ2qbdfWjtJ)?q&mJSba8tZW^c)djwiqsLqt{V|hVwb*g&JYg z-16~pZm<%;QUEjvqXv|I{+2+QwX?4%s7jbev1T7fdSMO+D=(E=GyC)24zSPjrQa(o z9o1tW*p)tCe*FyLTR~B!XZ~r?M`he=0?dQIi$)eg84X}5*D%s<8Xm5SzCq5#exRE4 z2^#fiK=7FH)-rRzD`57louM(rLb#cT>JvEObK&{$taWR@kLY{;0# zBqD)^0_L*jA1;WXkSOc&xAER%nGlu_<8dhzL*cb@5xrOh`5zx3H8+h_>x6(~p2iKg z4XZOjq@Vtb!$d?Wlk*-qtN}f}1eqv_Q-r1jG>SM(Eh2IMI##AMEZTVvlxjD{uGkFk zFNLM}8bhiH^r|VqClD)7@dWa2vqVf}y>_GmPAt1DU^sjE*&{TmCN4sGtnJLQXe?z? zSIXOlfK7E9?Q{mIUw%ep{)VXhW+~F6*^%E@U9$ubo7A>#0JSn2*%-3FJ;F1m39)G}!kRkQ z{OrW+BsQKsMmrN%>j5gO%Y4AK0>@wd*u1BEyV#2_A$<2b64OCZRnFT9EiQ1&ma{A1 zFu;S4RXcu9-tGh&OZF5rH}aYrN$%^P#-d3>a^@yBe|e5pXk7`3vHmanc#F!uROr7WTf<&1jg==4@snEF z575kI5qbC!uN`izX)c8A4y-#JVl1LM_0IBJbaE+RlLCTzU3h*kHsgEk?xB&*VP|a> z(I4*OEyKWht|xs+`MroaodSbq<#LXiZS}qODB9Hq_V^nqy4IF{+lt2!yR(2Ly9X)PqKkZ}0oO^Yb4Awg%7|+YbTl$AI~BUOz3=8vA`J-2NHZ5^hfmwMYBe&trpOiP{jt zt`UUiJV-ygk4Ay;!SW)iKzB!~L$XwN7c8_bWdJzIa}wJrp&ogI-2ExZ^GiFk8%62f6k4IzGTEY8N2}F9 zv)e$stCwbBDF>E#IAmkZ&N^z5CFCB?OASVX0*|{n&K$-eQExs=D6oX0-JHk%;wt)E z6?B{X=*t;m$vxKG)9VU$SwvC)a?M@z@@eco{}s8JX;B_#C~GocLHVbfsE1zyI~k>> z+pelbJ{LYx&y9;JE{Jx~Z|?xDZIq&K5PC3+h~F%E&is9QmJ8UielH$z0xSWZA<5eo z)d;avDb6`B9hKox;H$uve-o1FC8i)0)ld6dTj&#F_?y^xemiaSSh$`2f%OkX&VL`R z%`A$~A0c%;Al@?Ot*tu7kbE?cYAKEb0y^tSvXV}l)pYuR)QHughJSauGNCp?5p3T7 z0SOB|h}V#@Tts=!h5E~<=w~xPt&T2hR<`x;r5BfH=}IZy4%V#fp;gS|V0{Ilpc7H& z2rBMtl0*DH&>CR->09<$f^E!WLiN{2sK>*ySn6}3BG;ea%_vjB-_=65+g5dGyDjV` z!YDktFP>`&?;E{{n&TQatQS#oUKNi%a~yX}%0o*pEz2Y^gj>AGI>;D6^LbkXY%dGg z3iRqQ&%f#6&G?293l3v(au}Phe?T?%8eP^fMH}4?OG0$@5+iyS=SgRYB&uOHcF+vH z5wR@h<>t(z$l6RO-I&C|+vn)9R`32kdQH{`W*<64AFLb9+RKO1x-2)+@1T}UqPqAN zx!d!igj>=~sJaxW(p!4kW_UzTyQT4m*MVspC5`#lR^;ZUvAg&?`ZT^t85IJoZs_8< z>8qO34fMfrmFM!HkVNUt6J&pwMJ!-O!EcfLQKQDGgncsXl^$!?n0V0%v=kjnyZ>ms zAlMSRGj0>oK?l|+J=l5q4EyV=pc=OCSu|qHXm97yY3-ujX-LgW*1hZ`TpI-hUj+`8&Jvoz$GwZ|`Ei5J%$4eI#zpAnsN9%vrAkn@=8NXMF|j zoifmGN|p33kI`+T&oXJ~pwn++zf(gW2k7jVP+MOVRc68?p~L{1(`?0yt1(2`gS2-V z%T6E4kDj9yP5>1u-0!P8%ABt_9&_F~@sHzJF%v`hx5rqUokTp~6VKjy(2vB6r^qJO zvAbVY*ITdu-a%jbflOd}?QEX6!-HLvR@V@nUqHwcKv;7kMi{+w9UHHoqFGF#w@0Ty zQ=hZghty2PL(A9Wbl7O2TiwRSo7V{4z9D^qHGfln9};diQtkj!ZuLDC+*0wGO$S>y z4LTNya^ZFmY#EMBu%%aiE6GV0sLnD#YCgbw7UofAeFNJG<+c4Bm>qnt0jQ_leqFHr9%b|YiP%h9yNDIrMMQ5n(Mc`>hdZiv?Z70* z#b%F3bOUVpe7h}+z7Ee9y&~-f znyfX+oFEEDjSr#b9uqHeN$UR&qhuSwws~COmL6LJY_s&z{)54mA zo6J4>xS%dtl-GLD`+6F8-UPryf?>Z29BiSNPauBxI>G@>y!f$z z3(Z&(g-Mu7n<^+`sz2JT0V~Y5aUW4{XTyYaaJE!xM4XV*1O)Xp`T46dt**Y zj4(Vh=Jf#iB>KBNR#QR4VNZa8#yr`*&t5J_q^z=>SNAr>TfRz>D=%|i9lAGGd2PjG z%W!EOYzem~!Irtk0=G^(Hkmiedac0#Rs#Xl-oBA~q%!`{0LA`E3nM4aeph~{`jrZ7 zWsYy`pqGw{8ZiZVm>&5M-9jf5+Rb>9@)OY6Y)o+|OgazXSq@*44k|7q)?*QlXW%wTmg zh?v)hsGVWcesnTvv})U8z*TbzFH;vBziH%`v58|9jk_GkI96>}vGeO|M10c%w#mr= z%1<7moeisK9rh=V1?&srL2ir9Lxw`*6Pe#GCmH?URV?8p~~n687xF5?0I*ZvrfH zFj+r#%Q`GxTLrckk#jN}S^fS&k1b!P7m7K-NUW4tD!LV@Fw4?{|06UNFgJ8?t<{j6_i4f#Z z_tY9;%Q@?igoWmB`XRLy8OGOEo~s^D68k6@RrJ)+0KoGo-%(k>3AVlXIwAp&TX-Zj0mgjpjLnRS5aQU8))OAqb)9^0!Dq8xKyM#y^wk=qWSnowZTZ^+`8 zOJUv5Bta5Qg+e$G-%MNX0)`(RCRYSPmYinE&!smL^)l!Q5}-A}wnyl1iHC=Mgr^Vkw_=~bn8TFx>dYNPF!zp4;Vj*o({?C*MC z;BYknwskIq*@+3jwIa5kKg1GCEzu)S@2q`Hz>DGASp@(X#hC>NMWqr&N;y=z~by5=zg2<#>)m!Dg$$NzN ziZpc(vj=gk6Jr<0IvPrNEE-)iVG%uI-tt+%R#df}cH~_e)-?;_vy(UsE$b;IG)mBD zr=XT#%WEg}&w;SpM`w>AsO+CDfQGX>x0U#kT|?aG1?oF$Jmhs|KR4zmWg|SAwrCjW z5O^4!Lxadh4&fU!qFT#vWY%V-*Y+qBS-_TXOQ<~tTjt!d7B9h;t>Uy}%kLEkrRQ*M zY7&Rhu#ANQwluC85jWBodvb5{%L?4~`1=`cz;N|VuwE(4#87vGIlic|PB#s<>`BV_ z%7_%Bzjt|U1p)aQKkGoHWW=LLO--E{Y)cj=s!qS;d`2}NB7qqoo>CrBjv0(7F`}nr zO`yZAK4&_CGId>qzP^F&H?aLz1Mja6wtoenpZfespfw)<)&7It)-Un* zS)i8ter>QVTmB~MsVVI{#J$7F-U|TxIpClKG`9fpD-bnQ~7@Pl11;oeqY{O zcjg>P?db_yC<{y1UfoiAZ|J=NLBazh0eT05WZV@ytJoAJozq71q?xPMN)-(NR%K;n zX6%R^8`C|OVzKt>!emjt#ckc8h%*&_<5p8KVv66SY*T^?wGvpuf*ZWD?*=x)ZIV}8 zrPNqga^uehwltI?u%*P323W{1syxx-6C5_0*gZbQ?kTWGyyoo@&H>AP=G$=-v{}PK zDuxQ9^8SDr%b>E1)5eY~;Zl2rPr#O&X~Nngcci(%nNj0v84EooW^GlTW@q%33aBt& zjVIy#{gYFd4Ly==nFqYdlHq{hb{9LZpNhFyo^H{<$gBNwP|KWD0#6#QWpBkrk}sRQ z#(}W4+ykp~b0Yx)bk)X~`(oM6>~0AY!WzLWHMD94uwp8Q>b%h+;FV@q%&Ar2wq1f0 zG~>#dEuX;5S24Grq{s@`GFOx?xosfpmp9vxiMC@Z+J@OX2C$I@nw!%1N5?Ao;LQfy zzPhslm>s!Ewv`MGc5qxyW3n$Md1fr}us%5?;6&yQ0Wxksof7m@g+XPAVnis}6tF`E zVSgW+&!0;fhjPS^l~DJe4r~c(i@`3e(qJ!0gDV3EBOisCIc~5QxM_3;sXHEc@4bE_ z91!M*!NI*cHb1_=q~*i16GX`l385z1%o(UXcb?vaEa!a$ z>~Ev;;6B70N7Kd8RdO&1R(}K7avX5}ld*8x#D4Pt4d&zX^=lPO_NFi!wV?8B32rr! z8WX&V!Id1DgZpb>%d`eI=G)fdQIU|-2x_{o2d7yEu3g^@0#}|J!JRY}c;UJ#^CuA( z*=85`F+Z1py=0kU03;p)JYT}1Qw7c`Lv|M`mA5TH#wLzV_Ej*8dGpyNq*FcOPW-iU zR5G@efQ}6_j$FtFfo-~HK;?@v6@-CL(x6-oPF*0%PUnx@u_hpr-!m|AxQ`K&lIA3q z^(YpTeZT>O4X#p&@7d>GgK8x=@aod69IKoYh3OA{Q<1trb3!MAFCV9Itg;vYd^%Mwqsk+9Tgm3-4k49g)y0s|^%)isfF^J%?$)bt|| z$88tblC7mXGJ!2?drLmOsBTmUPM%{1sNFS{$HUWO*#&OP>Z}4ihf6t(#rpp8z}Axw z|B=VfVPZe`HGefg_&?=*{sy++C`JD74s2^W&6~c*lJ)}@oE9wJwSc`Muv3;zDYq;H zwTzq-a;TV|w}n+=Ix@PH{GOEN@xkuItlcJ??tJhEmxWbKtmjC4=6)=|RyiZ95-{$*@K7JKBR{cTvMt1a1Y z8UyKy`J+kHDr?Zmi{*J>mtf`y+XqM3YMx-{6ws;swc*Q7-CNf*d-0BzCO4{(Jd*WiGb9_v0N4=K&AAZfvoyzG_GGrxqcXw9& zWv!0IR1CA0ALB+B)<3*Z8xewDZUB^mP9n@?3)uJkTyO6|W<^Yn4)(G6>ZwSqv!NE0 zL)Xt4MtwQ3B^WH)9hf!Ruyij8P;z*z180r04tj*GCV5pTJE3RN9Hl@04sU9 zf6Gx#@+u4A>&Q|n9#hW|!87x0Yr%G5-Kj3fGk9du>G)gZ$mfBr0<#3REb-$3+vRvC zrsEx$*`2?tY&C_Y#QYGXr+1tR2Q z4%aX8qm`_WcTn9$J_?j?s*P&x=~HB*j&h5o{P!F3Yx&;ulHxD@nx;-H$x`TM{pg4| z(b7rvV02hmx5g1?1J0Vv%XI&_&oQ9@XHoW_%oUXE?$uCx_f*`H^9ciaJNOCEYRa9S zruYsUeoRCew)M}mUbFlpQM`iBAx#;)+ho=mhsb^1kHuV_E zbHitcu$Djt2irKx%wsYZ!+au%@k9#y3-ba37_uY7%Uoes$a?mE0lB9tAN53}t~Br2 zK<3eHOvmX~91s?m!6uP^khv1p_8jQoJjYG8hmr^~cNqBF7IQMzrlp(n*D|&=n=1Lc zvBDat5i+)6WNr`OIJ2Oh?dvOQ#FF9KVF7J^#Um~R^r)d!uO$=a%t zJOQl69V|J9I3Ca5><3DD1#CIy$VkgwbCHa@zHt6xlYazalq?_YN?l;)W(wm+M*3h| zSjgj(15iHB^c&tY@0Q7tfgJh?9BhK~zX11q7IYRSJNhlaw&c^KL`*hpio5UPt=mAk zqSl84K4BcmTwT2T=RSaZAlcl@7J%0{#JCefHpUV|F=SHx%8>F%rIj%K#*5zY5+!gc zouo!6nayLWgZR3|JSLo!)a0E^#IZX3PUQP1huiY}d0i{)znp~XZ};QWEg@rDs|jOE zhv_+CTMf`PxX9dAx)am6*C4?C_rR9>1HO*6=z0HgH*YDUs3WeK$HLSe3PbA-3Ac|J zd*mo#$^m^%s5)vc<}e=Z{TtY7U(ePO{Qge?l7F@9_#4=MBe1Ref55l2Ka;VohJFx} zCzj~R8rLvmwPLDY2M$&t&b#3DlolR@WS%6JutNkZvUTOM!6k!6F<4#3TdN(jQA*@m zkq=)vGllZX>v(Lfk|@*J`4g}esd7j$wR}Crh=HTyMXna096`XaLHn$w%^hGE4Cp&DpK-N*W_ty0qDYb40tduXo2Tv9QJA)r0w)K7+i zo0lfQ{LjM^9B-)wmOG*S{hDGPHdnCt<6YSV<(w!c4NJNE?$ULdW;*9LP3|Vj+f1pQ zr{wF=AdA3rGVX{BvJ_yw$u0qH1YTtQ2yVX#*wW>+d4!$ACbmx?j2vynR3ED~c(0+Z zn>l-uvvs(Gr62DhAB|xl6vAvz3?N&3!tvx@9`}0Q27#L=8CNb_$4=yRa_6_Uj!fK< zvOd$gANAMIl~dy(Bio-ogCmiWFa?U#+bLIXHjZ#g=jFX!$#t5Kg}_oHl=CVl;4cTY zlp?c#nd3OYaySorB!EI->j7(T%P8Z)+p)NT0N!5t5d#w&6^tcVJ|!q_xY_VEEbG^i zkF`miVoHvgXG;n4D#xu0Y?q~k&wmxLRi$JWoes<-x-ox0rhx6i2AW6vGPHTec#8zQ z^J0kI-JkK=<>t`swX}?JmTpKSFsfTv9~wMk3dnrO22tLAB5bW}kk7czQwdmL|4=rW zr6*6s8JYDoSw`s32DWRg=iAjGz_wzjx{KQcw#Q69*mF}8I3`b}pLnh8FAvc0DEZa| z7~5+ozWfOjP7t}Ifwa~s33%2HiNkL0 z`A=$&J~@y+R+-Gae{TQsMtXCO3{2kGhH^PxT)>nWm710lRsu&08Ss7(z#JVN3qa$& z_om{eQaUTpz|HCyeU`4D!<_X=K~-y zGqQRO2~uV5-^HA5i^0#NWvVoe<9$g#5KjVcog$8RrTbJkC}7J}Y#Ia}3b1|aFwfJG zdb9+#bVBynT7ue(z?Q#LO#xeiTQdFS7)_{j$6-(XFb#1Ho{PsM0B~}$BMBr2k|HA^S9NhTAL0j{0=q~1*lO;`o&l%( zI4))}nn+;YvR&3uIo48I`?-zGWhofJitZpCVu`6Z7Vg{usuiV7I8lL8?p?U5ob6S3 ztsGdqWOv?DjPyRHk}0H}IMP}ai>U$SUfnoAvw5P}RQEX{*gIk%h5;c0J#R=zfCf0u z6fkV3Fd0kAb*_wY&f5T0Dk3{~=SlXj$e6wF`3Ug57>uQqx?aQT>lc`gS(v3c6mybI zrmZAgqb7n|LvpB@NA1-MKF`>)L=&aR^d?{~F3aF7)BEDq9bkvSE0t3#@?-V~?->Uq zCnplLhiYx-K2N0ObWTs_F>Uw$<#TNRNT$~Ntj}d*Kj(FSH9+`3<$V4Iw*NN++u&v7 z{r^D4X+bg8g&C&`icL25$gyv#Y7 zuOiocd`eJO#~_VVEI-P@cGN>1SY?ThZ(wT)E?AG2`H@n_L(HNMWlfMhJr{K%KQ0WL zH0R)I)dbltiCAx}A$|Xz6fEaLKH?7nn=FyRg{GlEG4~s6?q#qA1jBR#7mG(I~#(tChz3SV|bF3}lP@uw%Vy@a8tCerVfL>M{!1~SG~EZaA* zWGTtbOv}~UkTLo;H*E}8X!orVnm$9XzE?u3KZ;sqUVWi!? zu?yUJKjdESt^E(0G#x3Mob5zRte0_fHAHmpe#!M8tyHSgnBDmmUFcieN& z$T^JTK>CWnVQ(FU7Y_y4=2Ir-L+!}xWD~>4>k;`{KyJhbF_YqRZm1GBQtrkrZzQ?7 z220!oF%juj!1mQ6mD@kjYS5Gp}uJ)LQ=`OJ4IM_U8dWQnf!r0PX zeyxHJar@W6mbGb31!_HD%lump^qvQ{WNyjum*SSVt`i)M5A>jsT~w-|6SDUV#&X7T z*>zdfLs9* zDf3GOytm>QiN^6U5krOP7YqQL>|;mHOKlI>S4_HKFL|q<^dAR2`+TF0>YEpsO4yjO zXu75=aBC%`KCEK9e+_K;Oc301j9dh^bK!sh+tTg3z%BzaMCkLsp1-^+vIj>0$m8b#*3W&-{}dqkSG$fs6xg1xO?$rH?ONA=O6^+j{le(uk`oZ5@W-+TZ0zx_2|do_5yv(XJJ?7 z#pu4vhA;|FVB2Iq>v0W3(EyfgKk~sgtm$3I1#h6JwVatJc`WRg9Ld;9eOK2YgQg1y zCnsV$iaoU`s0D%&RASpEn%tOi!P?ry@}ozX(jq9OQW!T(6=~ikBS9y}V;p-CZ?1G) z`P_}?*^w8^JkzZ@1|tzEy1o+jV=df)$uj#H?SVQ zCXKaSDQBFE27yWr*j|^CEP|s6Y)^r$V>K>#AGqvoyVBHM211zEe7J@Ahqp1Uhq081 zVlb`)`!y-uL9b`I6xk_yQFE0;N5^fo(Q*+FKfJPne18h_rXPzv7OF3PR?=d!MW<@R z!T<*?wfG-F5px7-WWx=qY_%xwJJ>{ReWo&MNGEMFg)TY*x#BqbgTqer)BxiiBfZ073%t<0LyG#5Hz zxeKNVla=Ad$h}{}z%rkWUr@rh3oOiHLesD|a2FH0jjazKr55sOV_)`Cd@GqlWl^V; zAu5kzD-lC#EY3R) zb|=PU^G*QCytHj@`01!C^rPBW^O`xd)wbW=#O|%5{Q42neKuwyU05=F!oU#Rdcc+- zR~TE?5~aD+d0_hsCRf#PO-Cb`PMIjZexh>xPH8&Vz&3pfWJ+nObPgAsir|8#NCdTR z9_H@Y7-pRW^1Zh(sz=dGFR3|-?>{QbvmsmD%r9ZGzXz0{GH;t~oCuS_Jr8Up_tpx4pw&yHBmWI-zmT!@0IhfY?+$D$;cLi-uY(T1v#}6Hdu(Mg zvQKDuB5M;j=Ujl??7Mr0jO1j`U9t zF>M=CczuwYpejwf)+Ne+e8`@5*&MDaUUN5~^7-5-?`#9x8xq;iTLvga-Y|S}T_w9+ zz#G9WWw!*j%(Gn$f6B2{z_#@lz;;a|uHFnzCAa^RRlJQ$A%Fxo%fl+C_iT35QtOXD`5aF2IYN#EUTKWvJ5 zRJt#UkdB)iCs>y<^OBtjoT|*(+gE39VF3XM34f=3b<`4yJl^R4D zrV-q#`^UagfeBR_Y5Dmhj7Gy)jE7K&h5l4vOWAKJ96&J?#G2tC8`eQ!+nAXWkh6ch ztxDmz8RUZExruiBh&{x;|1md<3{dUVQF-~Z7|KnBJ5Y+N{Lx(%Bj@A>8RY&ow#5Z`CLYIP zvIir!0~A^EN##P5O=S~MNSs-TmDTM zOEM3r|M6VNgz}NwiN621G`-W7anUTb~38N>LrNx*uas zM1XChwCDm`hR4)c4tZkJ&D;<-Eo+ zZR$OI-vQMx5|ne-Qvvq-IHYrRV;9ZkwB)1DILsYYfaTY~HY}i4f!j|q<=i=7TVTy# zJAwsA$6PXsp;Qcq%V~N3Si_c16)Mq)9vbcpdUjr1|LFkCTEu$-Y)5b3#BkIW1qNN4 zS-Ot(X{98S>uAsUm}8t0Rx<>lN4FHdC9TaL()mnhZURH+y22cEfrK9_jkIac>n znJc;bBUj?w$QJQFN*QtzgQ*0{lS5K_ez&=U%@c+Jq!%Qwm1A3taWxh==H(yHX?+#B zmrq3TG!-+zfC<$Ai&pH+c3{}s6X8%Ta0ko>Fl(_aGEUSwPUi0}Vq zZ2vuLt60(-0`w@;U5JJ-*%K88kVX-d&oZJ(AVWnc9dX5tm;k47BuxP>)|p%b@^hGs z1+d666k*R5nTAlGOrcb{AC~q}uE@U!Z23BZ?!0~t`B(?$VjVy|BQj~0#vs3=a-Zmc z%Nl{IoCenwZmd)e866+Df%RpK#{wwC0-(ceF?0jzz-0juUb&kuVQRhClCeF`F5={H zPc~i~rwwe$G7m84^pLqLOao=Qt$>_kky(=7YOIzp^V5Bd#|=y-G`x30K)s-(*2hY+ z`=B2`H#?7<7=u*1FuU#Z(;2;Q+GjSFu57Tbyw={DT6+oQz}}jG5h(@1&A7W6CNN^Y7;~(- zk)$}Ud9o?;Y~*Gz6Vs&*<8UO1oeAck?%?ET2aU!7_KzB9G!JobypMz9J=IS4;ID_Sr*>$26p4L3y6Zp#E8mEdk_mpbN!F7^{YZOdyN}+rjb7w3tWjA8ZI{ z;AURroSX>QnoVJE#UFsr0a+fJvK(%q_Vx*;oe;)-EuVlb4Wop$C0qL`$CiIT%X+Pz zq11U`OSYHhQDy*hNgb=N9s_GdRZ8ZB+#`Ed*#h!@QRTp&DwpFU?1%~8wv->+N{`99 zFcC8`7&mcJ&Wa=cR&x_Or<7LiOWkhP?k2;oK7#^P1qzkTAJ>yD%ssu0i9Q2kW*5d& z3PNg>KE*2l$#*`Joq!twUD8W2G zi@;ZAO9nNLni2>gP^Q$EpUG=G+}m``v38|4>`YGrbB;0w;{E?6uqA8z?}06I(aF@! z>2$}AiqrD(5~au-Z@V}-*%M}y^C!y<@gA`8S(f}-nWxFpQ8lrTnFseVXy_OThrrTL z*s0<4c++KVRe3tD2eMAkXTlY9kn!F)+Qk7C9Fz$ciuh>S-((&|V7sJ61lZ0y7N(Lh z4EH5eU0tSlkU?(lVefbkyBwq9gP}~WI1istVtp2DW+}E^EZ)71DP6~cVIg<-uF5f2 z8S=jfOz^&YIlE$vb;@U^DM23A&E1_%TV7N5XYO8z*e zFt&?^j_j=g<#iyyTCKMp;C7dJxs4pBe3my)7{Fl3rXy@GEMPdA{L{^&JTU7W&x6{3 z1z3OY^%vj&?*Q9kNW-_ZfA{%+|NiTM^`8oCJ@ENQ0NIP5;eGbSo;p1-k|5Xd93pm-?3? z-(;B~77G`F6QkuUG4RO{LPhtP%%p(BT+}bdJXO6NWf#~Mt#4;+kJ2+Z<%UF-c9#0# z22m|qUVq6ZO(MqJ+7Qa^<8-Zv{OiY3`eM2#gyFsjP+b5{SUY$Jho{@vJ@x9?5;CgB z4XJ7bnJlxkAxv*J6$i_Llsc|rJ=6-;u+2p-OD^UoV5^*w>3Up_Tt!L0s%n?&t)Tq4 zt|=)pWyxgkXg-65DPWsUq%`kwYr^v0Q<^3<5Y?uP5<2Fjon_&!En)6fROFQN!8S}p z{lMCy6oQdJ#L*Kr0&NU?JPljt7yHXg5*UJskA+VZ7=AMmV<1(gtyHOo}2prK} znqz?d=`~L<|4B4YIlY+Ra3i<9iuDiAG3j(8ZMTYH+P6rN`CbCdN%ITck8aTE(FZdBW`W)Q?)#;S7z1?w6L<_!U^1hkZx zvr(3uwc5nE>RW&<-^-FdY-H#^F}4ak3vk!3VKLc>#=$dO3S zA)oD?O(`K&dj3#=+Hx$2l0y@vKM&Ya3Y?`YawLq3VPYv1mYn&$;Xwi6Uh;-)S-FX3 z=_2N`(OpT($1u^-bpz)3+}lL`kBCb(s7TQ|p+ z5@~{7&p;|2*HNQrD)&QRn~8Kv|B*rF7@fWu$HBscszXc%-}8C@ z9H-|S*G8^6QVxdR2%E@1xGm>IgP!Rqb8PEpvSu-9@?3LeJ#}kY6VmY7IhRx6aJYlh z^fbmy&AmP)LuLSlV@*ksKM&aEEmgmCUJrrwRA>5oagtt8>$c3_-rUI}&%<-{L4O9ht!;JI9_7+w@yv9_@!Gxs@&O9mdvK5u|hx5SJ3x0U> zg#^8hWZP11jVGppH(bXQC$GXgd?t3%^O)@Y z^UM8s0F}qz0;Ly!_Br352b13dT0iH#=l|B>A!*vKPA8|Sk^j`;bvog5?HS(c^vD(kx`)AACD|(&Yw{# zOZQ$*zKo)mb2uD%iN$C)mcmz23jBb&b_KPdYHLBo+1X#%hbymk+yIQuEfNU#p!-YO2q-eR6*Otf~a zNsZSQZ?%wP$ zmhbgqF&V;AZwNDe8nz~$h=v9OF0<$YUgIGP;7 zk`uwI5yYm}fo+X0x>tntqsh?k0b4S<%+F+gC2P8RdA2-~6iS1^}qMfPzNd&LRqBZvf${lmU> z8#h|)vlFrm9IJZ(&oeiV%Hz9oE(N86~LvTtk>uprefUR4vmf-Byz*hB(0NrR< z`n>ex08Zw{Bwt>}XJbzo^Cp95C;L)@gbD%%&6H&qYp?SD<*_sR0-2O9dCjaRy*~6D zM>0=s;pB8v4Ei{?ah{^7g&f$AoYV%J)#b^>C|>!}PS2CCix_ie^MW z>EY~%)OZ(w+&IAL#+;iJwKsX#Op4POlZQ`QatT&G4BFnV{AKwq)hJ@-AME zElUA;j>+ex$Q(BXTUU9Ni5R9632Y7x0V`EC7je$!-{+C6_yNZx$0$vO8frb|b#83n zXl@pBef^j*Y%E1A6jDiGZc@zeWbQrP6$buPf)Bix+%HgOe}E?Muaqok0IM}LK8~T< ze;3QTE#Qm}$6wrZ133a)UBjYjN_nNJcpRs*bHFMqJ20=C^Q}AQGPua*-9H{ZW32rx zG_&(q>P<@doU-j8pGe_gZW_%RU6%R2V_6nA^v!8LCTTp=u$yYuGcIY(i_A?#+y_n}2eR~8H3aC7LqU7y#G>$}& zj<9ZV967@QYx&YZtEe&fp#mTRZrwoGZvk66Bd6&Ao=T#zyri7Q<+*1q#ZZH{t?rdF1Ati#c;{_LQWlR>j80m&o0YVcF`y zirt1<_%iB&@30=Yg!KTy?I&PMi7|mKo03ESHn3d@U&6Y54Y|;FSk$jz^Kk-L7z8$o zDtGCGn`bg)+!SzwK+sLck%nRycek)NF@!P!q^|{)?yIP?j%~0-N(og6>LM(K^K~t+ zx1)3`DZmn&B_)%l^tnmU$G`xkm;_sl{PP?)fbF6%bd`q#m=2RI>p-4)jBy|G58~LK zego`R#E1yZEd`jHJE~qSWn8Rtc(8dE-QS)jK<>wEpdBk(7xp5Z*a}`lCHOrm=2hgR zk)i!m@`sFVNxv>qWe*rphI<~^u0(ilU06sO*co~wKe)@=_FYg7ie>nezYqL zWV1Af%8Pqgu)9&${m8am!hE;|E6;9XCo`%_NpZtL$4oL<1UC}(CtIx;YuN}k4^bcc zh{C-dx9rXLSTZkRA=!?~+xs|OT?W`U0wj5Kn*dzbeVXHfo3-3Bc8A|%xj%}j;5Agu zc2px*#W?FrCCHy%e*-nSUPU-I6mDb*G`bLg^j5X zSh#B|m*&tlY#J@7hc2UTT}3YVPi4RsX%i>!^`|gTt~B^fYcLRb{s6gSabpcww5$9>8g~^nMss<&-%L^!m=~?l(7_GV{n4!=t;Br zHT!!(_hBJvq5kqQkY$i+T|LKC5|EK(JAeNeKx6LrP8l1+FHpJ{#}adXwQgaN3%BE_ zkG+(+Oz!is8_*IaSh2yv%*nW5p7kbnGqYk~#XQfsNDxZ_pRh;Shd*L-Y8=>DQ)5Bq z7pg4Oc`+z>%IEupK>|v2SAe-W)E_;?OjyfR+)A#zZm6=lO0Oz4y z0%Z5SoSWEZ4T5LR89df;vN(y#dH@}4#rFq%MTu6 zZEy&u<)Ts+kTpMW0X%cP8GMoQS}r)s?T3w#*QP+GCR7Bax{*W2S4IqYDCm9 zDzM1=#PLpMlS#;~<1YJ*V{Bss+k+!0ByJ+(w~&u~8?Yr?nbpE5#p0OLbPW4~DE{~m z&B-aCzRsK=x5|L~-0|7t+{|3P;B+x3!Ii1nCIS!nqvT448(I@ zaJ9%3t?+ABQmEEYe)$@6Jw2E)88owyH9h%p47m_N?I&QXz^yA;KL>1?XHB+N@@ySb z7;XaF`FITFmoKrq%z2p4oa+E5bCP1FWFt|x z^bl(jUu>$@u5xd7OB1m?(OJ9r`!DBj@27bVrxFUZ&u-yoJhlcN;XmtHUz->L;iUr>_G4@z}_7J<1BQg;;%LN=&3gGdi zlv9&4YvC2M*iFx3b@&4o?(|^N=s?bBMa^o#x^_v}?Tx@CZ1_J9*wQr0lO&5gIeZBl z7ISsKLsq|xOtcM^pL(z}{sxE3b2wVb;b^-gjdcyNvI3s8OUdp1hAaO zadrx)bA#A_{S)d*3za}S*8JB|30x88G#m4y@}L)cqpxLigW{rM4!9T=a&kRb&Hzgb zKxSS{dFFoX$B^mAT%c8I^lk>OgMD5J{u4$0`wPHUnMeIAV7nP|osqRx0Z&sAA96q5 zLVf5Rb{1yPEG$bq&Srp00Vw7Ho?oeelUxQ{^P^aPc~9k9Yi+0p+EHn{ghHepnZ5|p zPj8_%GYBj#tFj^0I#68!syU#_zFGuU_;nd5m9aF?hoy*LB<)+FAFvku4$I-oSn7#j z?d=nww1j3QD|vq>&|2k8Z@y?=|!&-bzDgpl@MMcr(}O5l=6us;FS zFLOwye0$Y@3AIQI7DFw__E}he_Yzyv6KE6**v}VmTIHCm0;LL2ECPi*ng#W{!|WpF z9`<99Qs8K}fb4C`_q+ZRb>j+3q3>mkGRQ!-c0K4rJ?K}!R&pr21l)WLsO5V;0b70! z4aa=K*b>)8c?d@Fki&( z@*=jErg1Pof~8xQ)C{h6-;n2TJ=lRlq!YP*1Diw7(Oh1_L9T$KJo_c5=9h9FC)E;8 zSIXF$pGPCJi0tFXSiW-;^M-N-uIXLaFvu`>oB=rx(0$4AB3S*B@5!bv*>qbEA*(SD zHiBi#2J3sWEJ|VU9geC+X{Y5fP*h|3xLUz(y@K7^3U*2*Y%VOK@cJc|?%%|4xC0r7 z(&8>;wf4^dwq0kymLQGS&OY(_g|&WJ4|k4rPjB~P?d@|hgW6wO!~y5<`l@2L%2j}^ zQpIVpfJSB>hcm-i>M`UTR=QfT-pQa#7xEFGs4?mvo&d!KptvNpic#iVPyi}rHRh`; zIL#GsFgJth^XDR6WyzL;KZuo1A67yUET)oD!l^Mk4dk;jr<|;o(Oj?MaH9$u95pF- z-C395+QIl3%0K>yxrl}7Zsi*NwZNA5ui`Ku(IvpW5DjC@--d;lh2p(C*nIZ}$Z_s1 z;Ivpmvr$gFqOrD$<3a^{Gij7xzrq~ZzF-h50YBD5A!LJo%=Sc)d;1LA znK?8{MWDP2tkiK*U&j$u2-|BoUd!R2uz-Wy47R2}BJ=PjM(iM1vzvL5%&V@1!_quv z?sFMizPD@}NQZ;SI5tKjI>r+zOy0hO(uemrDK6u@wJ_{A+^psZV1^7&D9;#iJY81D*7X{yq_hu9w)12RP* zTf%X!jH6-&jdB$SD=XMvUB%(*DmF41l*h-AdGQo8H+zJwt%M_3Ct%b~%=Dz>cdIkg z*vsW{!hR{PpjlnTVYRB}_gWoCwHkKIWvorlVdxHqS1C|EX%hU%}9 z7DGO0qRe{{R*dcM0bAx-a~v&3SmwtNU^^et#1A0TcMB^o-(YuU4hNYfG?w!~p#o$p z0M9X3mHs;^m2i~L3R7Ep_z0EcZREAM0=0h;VEZ+|kU-aa-+55G5D4LO+P4B-?{EKo z{Nq3^`%(_j$+|T*HbCGHNqrUeT z+TS~R=Sc=un8n{Ydav`27hnG^Qe>9#`D4oc5Ztotk2-!nWBVOWBA2k+{{LdV{eNRy zyCJT`)9pV9xE;4cQl{m7!o-`TYHyP|-Y0bVIZL<<_QWtbkd*wZsZa}Yk*mTMuKWLq z9Rkz9_rltGd9$;3e=&CSn zRqZ-dBcsW$zl6PQRe(7fK`u!b%n(L;bPT2pyf=b)r};3b2QeCr;Jxj~2cr{HPPgQB z6}xU=y}K1#{uZotUq(%DM~;C7tsPT(2c~0T ztPsZH0Srf4QMUc4McS|typFB#RZzm6*Dqn2%%6E3C6}?SYOTWFQl88jsg$&mH73xJ zvOkh%dqvEoD1n{P+A$f`FdR3;QImBLhf)c=PuNo0Vk{Y#T({w#I7a&87#VQz!SP`t zbOYPT2sV8;u+@DP8%{UoBCU9%x8h^cz+|ciWAPr0rTQ?&TDOTPCK4vblBO7Cj3#23 zN<_g0IPY)Aexwx*?JBl{-=iG-9<$nYq=@>tL*xM;qgEbTHEAV5B#Okz@=L zsTgQ{la8Cn=-tSMTCnMKqC#NHGDvic{)(o6?G@}tePT*BAL&FoWs8Z))IhJ)FMMws z_-GjzwoD9LItFbMA8k{{=X)oD;kX}fegD8(PXHTs8whMG?f-$gc^y^by2^o$Ft=8* zwQC_iDw@ivBvU7h6J@Jp{>4a28Da_BYOpL2^MGkKrPKk;rDfym1w5UTvU+)%%(W%3 z<#<@LTNSvqTQHmK!f?`uSMdPG?)TwCe@YxbM-oYl#8P4=@*$Rx@)mDnItHB}rWhaz z+`w+A13Mkpu<2_-q5Fz3+?m^Pyp5T79gpIDDvpo6aSRWnFnXsC&b*X#Edd!P(zGyQ+L(+bFw@hEsos>77a27J;Fw-D{b*=@ zH2hsSjD%1PcZ(_2La&9fn66$M=X2{|JQ>A!DuMCd9*py|`Uf!8(}!`>!Gu4EV#Go% zWMaEJg7u&-xtgO6pP2;4l1Z6cKJ+E=ray(}{Ruqojp9Mv!0Y}5hWdNJ*Nz1>%=yDu zPxVQ@>92t88C%Qy$Y+Qk&o*vBK{|RG>UVJchOhkgH>Je;)!q^FEsA?L<^$^}V5xnnB zVD$EFObpz@$9NKN5(&J&*@L&eQM~JO@V3{+2Rgs^IT$j6mFqn*D zIN`N8M&b#1miau7#CkEF>{DxMD1z}&L`uw1GF%EW^~J%WrXdrHN=@5|z7&RgQyA&% z#b|FoMtTPDA(q0}t-Bb$c~kmtJet6Ql|VU?#HQIRz>HE_GOzqxaXQv*ktk;jb);PR zw^>0G)o2WJZS>911!!}8kx^z@vFSt)hMfe4Vm%m)_v1s)O}rntjd!>2;{Ba__;B|= zM(#bpn?wq)Z4={B3)Of6YlelIW}p-?Wekj_k{Igi$57u*jP~5d_`n?u-@J{FeSLTr z3E{TEsyiY+%CY!^cnnBgq7YdV29O)`zj=ZA{&K zfZ?9oc<1!vZR{34_B_CF|3eHV?_kL3#dI`@$$%!tbOiCmppIO?Kv9n)Z^V^+nO zhoX3+*)nE_Qz?AV42=3T(6Vb7#{Sq7zs1oGx=NH>=0Z9+oeh#4Z zUh_Aw{bis3R=@rkKl@(ndP=YQt8 z2z$p*zq{;$Tkojq+j_72bUc@T8~zSkk?&Dz|9`M=T$7+g!|FsWbX}Z-GkUAkq@9R% zVK~7}ZMSS}$KpOr#(d&5{8snjW5h3cVXVQqre8-rKv4TVwu1k}M(78TC9h~#1vru| zTn%4GJ#G}t@oemVjH?Wp8kg+v!1{~MJ zm~u4C+H~HfA%cdqp<~X{<>yn;5T>mAR)t_OO58}PDxPCe9tqVGCp{WpZMo{5Jro76EM)v;izmW~?Ybjor{xrBzi-i>nm zb<{g!F%|3Sj%zKL zjz%z_h-1ojFdj7oIM3S=ELvgNz%N=s%-dlsuxy1BM9zO5`(`KVUEg8XxQ1-tKQL>2 zhbj9C(hfKFzOzQKcmDfDo1nmVZsV^&Jb@o`WWS{m412(s(p}0!2{gHpCI}%QVJ%X& zWog}K-}7f_s}nQ!bu1@ZP_n2ZxQs2c6?MH;0z?F=G?dEgohXO9u@ds391b9-`K6}s ztmVf{uuDM863badJFpt>#F}{xmCz3;>6ft-ZNVIy(=L6Lqs-Ozi%fjZ_JO7{g=7>{ zMi7&fwI-B1bKUB~Mz~FaE}OirNQ=m&8JHO{SbodENF*p5_X$Ij{5F=!n2JU*5wpb@ zh`||_yn=s`Be|b9~z>^*USxR)RZUOC!dOIcqmyu2QFcZFp+2B=_oNm;j z0jyhoIw$!JLWaUy15A|Av{i~vl@jG609kecn$ zvDjxL-Q&pLW4>g?4$C#BBP~dq9axaoB|)gXqoJCxuuQpnxLdLCnquRbpG)Q@ZAIic z=Ce!?PWI2+6!RIJcY>IX1wq3-dJ|OiZmjz{u-V;(T|FYTds$OjU4tgiFTeJ#iPt5i zbD}zi90Mb^g$dKag5jX*BvJNjSnCR5+h*#DjoGLpF5>30D~@S1 zjyWTVc{3p{ylFFzw5i4cb50pdTJr@_>-3`@(IuytYt?An#$+Oi$#^fO5(Ah>3}Cot z0E4}K80}Ty`$N1>0Qguu0oLX%IFP*3dB?H!&1v(A~h86URdTEiqu4>>0px;x?uecQ6&di}Cm^ zjK^?no}3!}P?aWjrFBZfiE#*h)mNHmF$W)wrZ zg&D~kjw2gzuo6z9(iO#q-j8A^fq9>Sc|D3r&A=Fqy>9kn+ELFp%b?LQUNuXeVfIrx z7DL*wuo{Y?&=x{fi=z}x%KI6_ny_t5nKot()%Z1YyytZ`Q-Vn|7E9$hSQe?aiN#P@ z=7v0hu@=FCrgD=xR`@lW1Z2Vr`2HEd>wnJQG-P~ojDB7FuK~vY>q`OQ->+AJ0IwhZ z6=?me-<<=s1h=1nssg6J_5CN1dI_rpAivrEJ+NH~e}}qt1x5e=haKxWsvZ9+`I)O- zmr(Rw5i^@UIZ7QtDY;87C;iDjBd7@ElL)J7|SS-lhUe#&b*vC@7CyP;N*kJ1&GuE9JC zu)TQv6}bI1lS^Q`5^O^u*n-(`8^+BJjM?3oaDw1uOMty-o5&<>%q2|BCc;vGbBTB5xNBIT88I+@XHSPfjoLij4C%??bP z0Zf~kNUA2ZkT6oiQ5|EEkbs*(Cye1#1mnGQzU{$`*vfk&ZIX{lVEbFmyMMoREa)xBMz5j}zlw@+1=ZkXtb}eLAGjvL2ZHu# zqf^uq8OV$B#*~RoHoc7N4iGeGRkD4UEOxFc#~=gzb~h zqP%?6^oiVYlyb?agF!PS4C`3bFTn=}K~@7dun}m*78&7Civ$SfV)Key~C6mY3E!lpQ0xj4Mv|>NdhFz@#bS9s1I;3>dV8V}&sSt*e0SqSt z7>WlmmkHbLO2NiE=PLK8rk zNokl#_>u0@Fky9IF6u*$z}@s=#R;Qs22hLmuwjQp9=&9Cqc{*1AjvT~m9Q`#<#ias z7LzenP5o?=zcV8ez+&!WH55QK*o{J{OY&Oz%rNjaZR^60(CDTR)&!vNZ>24|a|Z=T z64cH|31*dynECQ#6gi*pxf)5C(x;SSFIgIvVj-jxbl&Y0<1z-5#tk1P%phirkmP#i ztq6({GW^WTRt$AHqKv3KDJy}UdW~N|Fu^qQc6lyr8M-ws2kpyK?P`2CO#%C496`@#~cZw%u0T(=>ky~*#3g4C8#~$T-Mgh!8Me-Fy-T4 z+X#XQ%n2k|Czg`*m9PS~8@>Qmf+5W5nhNy9q8OpUQH1N0j@h_@X$Au0CT4qLnCMSn zq9=*DWD;rJLB$urUckmyn;%=2BpS!K z-GdRQ2Or}-_?S#!I1$HiJb|Ia07l{i7`0;pY;$oN%tc< z#;jh9Tm2Zb`!O2r$9Oa)>^4oJHjOyex^-;Zy;uyI7&oKBx_fG%QOm-FZGymhI%Y|! zsp+JRncgU-k_M(?5fJ23id;5ztZEu^!4O8ZAch=EfH}eKgcZYNOa%j|s2a56qDbJ^ z{Q0b%#9YKdI%K1wr%>v0upSveQA=Vm5=SQ0k0~k=A`!eXG}Zqx2NTgKreiTNe52_b z8^-eCLfD{K$G#>Vh#th{@K;^SM$-HeJvF6V2LO+Udb zSuFv!TC0HCi@??cM(4pTff41|EQeGz6euRhCeyo=)R4IyMfLeT)L#CGotKZW_v$fr z-#o+m`)61geu0&dS6F%d6y+xmFn>3R@wg9UfyidoG}ilV#bmezGt9Glcn53Go?_$a z3)G&!kessW+t>25wUKIo z^%7g}Ut?|f4c129WBu)0R3AUW{M{Z*CPH99BO6f?=2El+lhF=L-_o)Cs2|nm53%v= z5jI{v!Rq^GSo`o??%&q?w_@y5c=IzdkNd&$Q(n#IYPelw)-!<{Qp#)TUJ`{zcd`57 zm9+iAH`x358hh_K*59D^`ZX%ApQG^dCzPMx7pGaWs5EZd4tIdLu{o<7Grb|q{ggod z?L!nkJVyDW+de!(>BAG0-akj_<0};3zDD}-&zQe^3v<130fJ;**X(vIYu7Mg2avwg zhuVur*m?V0+U~m-*#7t&TZ7NBJN6ozBQH^X{UbKtKSurOJuD^+VK2yj79&B~#HO`w z35XRQ450e*CzM`3M)l1Lth{}RwKuQjx_E7DYj0j+g=7ECOOepe#cYv+R# z>?dr#_zCN8e-=0GmG}2iA9;-R;io9S{uwkYnn+l((OYyhnP*t~N4Z^7cCB2NDOZ%{ zmI>m|<#z&XyX0JWJ_NZH-H(lM5Ose5h0ZR_bazTXjJcpJzf^wl5Y<;dWA*LNsJ-WT zJw|=-1?oeuu=4Q@O0QlZefJ(_l0BF+9gs;WhQe411u>>aFn4PJ)n`vofBh1*S86`5 zzI%z{yJsj5zD9BAr5sCdUw~#)Gsz?-4aI;fw)xKkw!D@lVas%p02A2O0zT=hQdq;N z9un2T^7ALCym^K7H?Oeu{v|d>Ut?qZt*i^1!|zZV9Yl5T9deI;#zL|exsZ*ufGN!O zYA}GMa5v_hFqR+OMEUh2H74J`$J*;RsPdV6^$O)zFHn5(48^C9Q2zNRF?O1xWSLTB zvZOQ~GIdcH5Zo^PANJmZy^Skd7QH|GynFAA!`PCQMG`rKIVk63Qp`DnAV}n#b4IzY?)fk+SjnjhUCPgT$?H1f!8mP zURy?PaS4Ux6}boAM{;2q$+ydhzg|M*^&*0=<`H~JHslG3Zl)X_Bux&9)-qb@yLTUf z*Dn#Ce}~xoJ0#z8pPEO0`8|rOODM0efb%M~_!i0e7dW0B7XZkpdScXrI02x|CS^0e zCy!*_q!$;p`&vVObrYH8b);6-kzU{#*wg1B59w3-|WGW z-77!OEG;3v^d8Zrc_fzK%e-3o)>e?5e}%w9j-6XHeh;ZD%erf;6DJ1R zq#s3Wt(J>uZSZTv_M*P{^8v07P(SzeE3o~464<6jz6F~OVD(o$Qmen`tNy)TzW)7) z?Js{a$(!ugm3=XY-*Zx}*l zoifGw%>%RpTR{FCD3eepAu>Fu6qJ+&`>Bxw z%5jl7sqDN*{Lu`2#@mRQZ%dSxz?O|sS{>A0j@W)0*xo?Iegje44N0dYLDu=ubwoW@ z8ISDxJ4MKp2`kZh5__Swl0yY0X;Dp}o$#S{u!zEo8L8t88-5f5q;uyD>^X0uy7>TWR4mM?kN}p{{b|I_24qI=plTjL)_5IB*KLt8`Vv;)KRaSe zCk3A)X1Rup>4wzN#*BAl{PJ&}puWEbaO^TsCC@<#3o?DO&zqFzsH#2-hfz7)7GOhC ztyAkwFqNIrQs1lt(WPhToE@q;P|O2m%3u{0J8r1}P{yg80V)Z!BYViLzd-r*JtW4h zNR67n^yMAL2!iLD3S!DJXFvy()#fYp8RO3J`0aQ~!opY4eFQOlhqIS5aInZo4cMl=yxrI~5 zO{uRAFV15SK2v|6_rd+3#65s|+&Q3@RZQxYG!QyL>gQKDyElVP(}A@>aPNz`iQ5ab8|(d|zbCBK-C>&L7So=ys`kMzaA?3)9aH0>XVxi$rvp1{xs& zjD;zs!w5JPuw}|R+o_u=^a|J#)Dny`ntS+c65-wVXpmTq&qPAHY#1nnfKm`BodNX- zP)`7rB%0^PAOJjjGAEkBOzUUlS89u8U8`#|QY-1W4ppbkzsJAJI%7sUc`s~X=ZFCH zywNC8vAEHUh}VP6{0r24n~L-;9RactARhrrQK)g`{NR3(0pc;_wzd#__FN*0Br#%y zj$p=je;P^lc`yKE;y^Z~K2yyr_IEM{%NXW>VgjwxV{tf~-G6{1w@W~p0_jGro>s4^ zy&SFO*Z=y6ErD6o<`mFKEmig>>tVAdqkt?%=ntmG5MEh8lLT93?Y!bzYfx)73DmhB zNsh&NmO;&bg7nYxNKDmluDhF#oBBMz5&uEn5PTMIe#KAWnI+IHIp!<8)$D{?@sL zjtDP;v-gqT-WD=XA%CNk9oHH6Jw6jz`Rkf;0!bN@AtaaH;&66CvLS+Fqr$En92-aQ z^-H98Hx(f$_qr1IwX!;AvYf9KWn1M*@|Z#E=op##1qAOu!ii@RXO3}cjN}I99-y?f zsm)DILW;Hz#~_zgHXBLwA`$e1LE!8h@i%V~7@w9}-Hd4rrz0-J9zI2Ac>$GZKnLQ<1Yim&;)kQ~LFHxZj0hJSJx#g(T(=n%-Klr~+jivd&0%-7lJsUCK64myq%$ zl&_$i0yJr&HjVBWYWr(aH%CMAQ-GGB_EW(2V}MI$<^-eAreVZ~Z^M7*77}yQXdP~& zn><%C61*2mG*MPWq((ZLwtyx{!|&G$sGaP95i1(hXBLB`c+=ZkBjcrL0(OCVA81m- z0YFjP(1L zsGaXC5X(N-C1*tLf)Y)f6O6T$l9V0M$S$zdc?^+O)*z zBl~h@V*`s;8;(3)sgXOKn-%8lemJD&x-JEBF)#J`sm)b>zuQ4Qbc*ErHSPEpe**2a*MLfsYy=@iQQ`;unLwBs`uc?cYmbo|AKc+Niy< zdgZ*R6)=d0kY8UD##(}iKMUA0l{Rj53VSX=8l43Mwiy#yjHyNJ03**O>X+*Ckn%pA zvW!=+pI7soYn+?N3TYX0)B_gQ@zV$8%^M?}#3- z$bHFKPB|T|Q9g+4TR+2SgLE6n`wtL!`2?qK56&G{+JvP73 zI@>e0(FvSAe~yaZr=*bh997Di@%*JtMM*_I8|9IBu0lHxJHiMbefbh6F0a%T`#j?U zEV~KH3sM$M+jl9AruE6i_b89mQ4)CVNC2tTC2Wm);2UMFvJ1hvIb`>@QKn`y=O91N zvq0{P_oJj92Q`9J&fBIq`g)-tva4%C3b$djN&Ru`#Vgd04isqTJ;^+$>>KxRUH4g& zJ>wYi%xX5#I66l7;S-!08AYCe-!_iw+7>F&b9J_GP4FDh`p5LyS77^Z z25di$-u@Qg{Qz#i4A@47e*oEUV~!yq3JK1*K7d*pt%EuSXrhY_`aBQ@G^~3-M>{B} z<;D#$83qnFa6+)>ypE*hZ^+sig=JKfwX7=L^5axwMs!m)m9EU6>A;rk#EkxiJ+}~^ zG2n38fL>rzq7ve<8+6eb^ie^Na1ssl(Cv57>vhoUx6mCl)y7!Mi#!e^1e9SQ0SbX_ z&TvgqTKP9Wx5k#~gtfgDv>B}!RM18ZrCtTaP6f?&18p7*=%dysqt>mWHmIUaBaHwe z8$;yPLm|Fl3NoX#dZd;lQUtYpuLIeSUm5M=_cE5-s$Q4GLc>Gw4-X;t@~MjQb!zB# z>e3%dQIE}*e z()#H4wRu&o0R9v4SW_M(cV`Isp*tu$O-LBY0DSX{!0jKMihLQwe*87ZnZ!jY!!4Ao zMr14|oLkK(zI_ekl46v}T&BKYx2O7_Hd#*~4tpB|HX464Y%5tL-@TM{I1*|2JudVE z$3QWy>6CJ;lyS)Z?NCcq#-3|N8$VEcIfZ`k0K21B9FAIWH06Tt#T*(jAH>PkrsgJ% zCIzG}^ed^$DwBlHCWjnnYM`mP-hE*zz)cjNUCrmi^-p0wK39V!Z%{u3u!uhfmxc9ZI z$n9_8cxoI+7Lr&Q5qB7cEbPQOgn*r-I2Ng`jhju9c|c%GP|K$4(~{s!2et&6jN-B` zu9FI&)5=MI4lWGxD*C9Rg(@1Tpn*DatsFXNV?e98RTa4_vf1+*%qr1IsYr09G;mb} z^UQS{Y{HDL{pcWv{4Dsb< zl^Mgez|DjDx~;aH&mG<)!8di?TLYlYbDHf zz9yiS0FvvGP1gdavyhtUB_I{U&h)g@%98Zz{Qe{K3u$n_mGgt=fjBv7=kZMGqTlPF zQ7@}?%%Ah`R>~+J`>-}Xffbt_d*c%*Y^FA|7Aa<1B4prrLsixNw~Fd z^WfOxg3m-it2f1rOi)We8#O3!`xV%JDX{!pK&yZ5OaK0-KmQfj{>i{LIs6USbO5Wr z>d{*LJzw?jU4H#XHMSoBuuewxLH9Og`W}gqACR`+7B*25EuB3aQxO>&uY)>z;4#@1 zGnHm5ZM+L3Qi4VUWi&IrHR{KXezd6Z&ICV`Y9m|~4B(~mPk zoTPwlzW4$Wr&z}oy1CAjebSj%L`>BQ&@`Hu|ZQaCYe^t6Il+i{RO;qSCKm&tv z7Qr`95%G|r@YX*KYzb-!epw5fy!#VMW`h`2ev<)(`L`;Pf|i&%^l{SemwyI8f51Lc zI`EBV8-05H35?nmH1{@eGU~$C@Q}zK^y$rI$}6L)9B<+k0$jNu!9-sUy&k$~qk}FZ z`-7@z(FX31!#`?Y+x&F*v6YE+0DXud}1+!wb>kt{-A}HI3O-{IhUKvaX`zVK&8bI zCU__#HUCy>jY2Ng9J#f$J{mzZsAx1XLazFkL#h7jqbuXrLPsKjWgrv6s>gyA2T7eA zIDGvOEjn;eL$_DMpx+XQiP{~M(a!PW)KDe}zhYEA55!NgX*1w-R1upn@``3ouEqQA z3hX5G?1DyTm)E9IrFI)-^f7{3$)ULRGfpPV0t$~OObYz#TM~n+?STZ1`IwEaz`Tnf z2pwTGlnLes#R?Xu=dj_XgoP8~x97cgP>!I20$sMr2FE{m!+Fpnba;FD4x;G=~ z%mi5^o;hb!mbJ8Y6M{AZT9b@#+%haR@P5}VurW=TY{fdTRq{>4!VXThWOUVj!CqpI z^l6l9tGX`GmhQAJ^1V75=n9Yr4bVyfOO)jD+HvAmk=cv1eKJRL&v)L&srxnpZY2k$ z*Qu+hEhVJxB0+K~>L*(r!qm$Y%;wgHx-Z$w`r1~&&4E4B0S!()lcv?7QOY0nfmR1c zj~+_u=)TP$%*m39dyx&Kfn(WZI@*kEqS~p*DJ1*3WC=7x=a}R&{|aEs$m{1c5(Iq= zY*}ZWHk*YYOV%ILLpwEbIH*^a_dVf&0eC04Rku}n-A+we^x#>_XzeGopGId8D}et!hTF9-ou$GG=j(CJZ{s0 zEKzK==W(yo_b2u{=V_fK9sHYgwl<3JJ*32*OIUY=ktiI zEQ74ghhq~`3rsC^M(ep3@bi2ozRG#Y*8%5-dcK}Sbh)lnhTYcG9O%qD@k}H5=%rjo z0HR!lH^5$3H^=MoU5ntEdrz;0eqHrfJsiUPs25w52AiHlhAHGM9qHB4=~M)S^0~U& z6VlO0uuf-ox7k9c(L}FWLqD5EWPT9`_6dZ?9^!cNK2W56&<1xjjuWq=&IzuYKI-Vp zxhQ?dYy~=YTRb0{N~*{{ibIPFCuWBLTV_3wM2eBv%fOc4_A9XcG%)=AQEMHbe(vj+ z{{2sX{wuKkHvzW41#T|`+fRYpe*|nVgJAXbH%J@w#=6}fkhkAP(0pAOSXoDhMn=-f zI=wO);PKD}V+4#4G2w}ajO=}ykv*W%+$c+()tc!igxt4~B`J>a+e_e9m;0g24_T2v zFeB&8-y?7OLD-K;7{wY}rXveElJkZD+f@SFN=!V~-Ck3G8GZP908GOBC9vh;PQ$3F z)shy46yp5OHIz-aP#C^~_}#xqL|FmvPeg5h2P?7w+sHY3^qxx$rH_KVYDNYf@Vvh^ zL9a?iE=vTwgLWy4lNXN>_L?t%ZNhX-z^c*^RZ-lJBej>`3$SH$clavGwqayghh;Yl z5fjq_88xe;E5;5FC>c1OS(ku~9E#$drN_7=!1l;($L7#o?2o$9j-M+aDg*w((%>9u zwfhnoV`N$xR(**~OJpUVz}e#&>^n_39S(dqQiY7fLYO$Rljkb<2x zhqVH2^c;7jj+^?6lwU{>-9gE47j?G*apTqhcwnp2?r%s0I%XcivDJvi?z+r#8mG)g zDAQPFzc5*XLBgI2oOAxOpUQoj4?Nr}zW}zB6_I*ZdhjI$PuVRTJ32Nhgh>5?7%xr! zok0!dHeE$Epp?SuxD(ssZtTpA;o#kK)CAbJQ14V#c7zxh%7e~%#HNgE-WQGQmRf(Q zFxIRFkYtH-s&=>|X{(IT5^VBbWd00#X!lj4S;jfbd!-?SdR^+N3adYhoD`#-fmyp4 zq+DZSj`5cV+GhqprPD)gz!QuyX)@cR z1r!THF!QCr_HzKO{+Y|bR#K5|W(a|p#Ukm+$8IlBDoFN0tJeivUr-I_PaCCvO$AVulujfEdV{W)Bkj%5OBP zh;OWby5KTDT}}j92W}ij+ND^fzogFgb0W3+XDAcII`_cC`)C~O0fn@r*D}gahY0(E zbDE7^!ls^EhxT3cT6Kgsw{SQ$haI~M`!myML{6nQE1jY^$=K(TXvQiUaTIcn(mv>b z&IZm}u$H@#!}hEf$5Sqxcr21(qWb0ou+{Z+^;BbBgZGob*6P8LiO!`-l#ZE>-bJNW z6^9#Fajo8#`OWdy?@_PJ;m^g$YBrGB*~ad~B=)@H*c_dZC?^jBX54Vza4+IsCGN#R zU-mBUt9(LUL$W5Ah0^X|#XE&Hs|SIx`-nZC$Dqc{4?0G5V665}zH9W@OSGlv;OnE+ zsiRpTcM8Zdl+A?xW-Bi)7H7FfhMsAtD9CTdAvF8@{X3Q7B zw$)LP>BmSF>qGK59kU?gF^Gf>Wri}=ZxA#6pI_YDFCw?U z3)l{$A3VdLuDr{<2O62B0Z?nJ&09)m1`2o+gb+aRcY!m1P3$EeQW}7u!N5aV0b9s{CbeRf0wPcEOO)=&W5w>YTcwfr8t4ho zQU;j-THYKFCN0gDHn0K?{Ch0{XTCAFkn^yXIB&cmk^QvwnlL!)k*3di{WDXM`M3ED zY}9rQo9{@Zpt`pzz=4TZ6?8!WtAl^qD(v$PBa#}hrLoqMTEr?c3$H|*l(ln=9Ra5-(`wvy@-toFLuXAu{}MGz1Pn$U_GT68iX&($mD!x z6b#8GaG54chOBt}uZu zNsS0(mG-g%wfsEOG%1@T_0^2@>H97pq}@l4(PypCd2iLOimou)qkhoA`o#D}#FlB! z1hx_94S6M~WeW0%m%#Rha3lN{uuWU7NE)n&nn_~hLi_koYCY-T;Ger_mkew%w6#4( z_8l(jRu{pSFR?@7D5q6eT2(}v>B_2(j%k%llUH%9K5BiscW9)mNS&lv64>Ul*qWaD z;)tydQa|@q2R1r8bHZYl`dX%_Qr}e4BwH*?A*j_RVn>zDs901_=BJ*0!TBoVmnh<3 z`YE=ZQ`jD#LTqDAB8vPW!5Du})`qr#IHeW1RREWLCJyInMSu}yQ}!HooKx%6VnD)9 ztxszD{+X%BcAPNk=XImHyA80Gli5SPwnVNk&u@OM?>U?ud_ICLc4}m62Rq(r(O%u3 zo>5sUgF4!SrbI90u%hEs%3kR1r5jKI+q$-&N&0-NfZc}^QhIUhGU3!=k{Vm497_b& z`pal7nUD4H|1Dtavv}Z}dVtKqkvN<99Hgn>eyN_1N$8rxierDt!K+fM8i=m02(aDt zjNxeJJ`hhbHAVJweP7a!Pr0UwZz?B~9N5g@5Z;O|_Gh19+cAk#=N#fsf0q7ki(6iU zwh~w!h_i&(RQsRm>rSsJPJ9B}W;}}3`*T>I^vXF=KHODYB1}V;d;t|*)yIwYg4hh4 zw;VRjZs@ma2yJa($?n1F>|+7m+?%=Tnbp9t*3T`PFuWd{{vW@-SXYf6HYe|kv=f0X z)4&OA3BDMaWeXXt2pg@48r198i0!XI;a6b$g`n`CC2IP2{QZA5dDMS5uq_+DN5SwT zqUN7);=Bp}V*-${#6jErq9n6&n_)_%ewfHcBhdo|cx9s@OI_j|2V~WC-ay#!9kSNH zDe@?*Vn)_$XbD<%U|TX0)P9e$;RlorS46wEWZ=(LO>Wq69X`(u?9W;*fNi@=AEN@1 z3M{I6TLLd`g{(BX0Jg06Y-VucH6ZO70@JSxmT!@<{}l-ffh~de=SFOYfk;$pV`yaP zhfIy0VcKeXsS3U6^s382p)41s7@a(M^u@rIP6JiTd*lrP>?G^a!1{|A4u;;X(6*J(p7+$V2$G_b$7W0jz?Vx zSx1mD-&LvV95cI;wfP)CtAFOt2DW?#&cCev7DARA@Og|V?=A^p4&yjgFeR%mhQ>u- zX{GMU0YF2oiw+$)y)yFiFF}S@k`<9yN7%tzMS)^6eo}9$Dqv+kvbAiE`nfPsG6k7yjK&i`N4U(U8&)z0G;qt+D6H495U8`bZWs|QLy681 z6txJrfv$$dbfe|+t3JnsXpGT|g;(&6nh|mhiTsd?Xwm^fgidQo%};`VepZi2^J~^3 zN=i0g>s8E;x<$XyH#v!O5+X5el(lJ^>C63&jfN+mkp>{&6OiydjV{&)7oum_e=sBK zCE~V#TCfop*~RZlt?jRYEu~wiFMUVkbQsya3~ZU2OrS(fN+F2RqV4K|w1uWUAICt( zK}#_g&jJUd-ooa@1P&w>*(gL%jLH(+@|D0g;Ql4B)z<`Ta2c^B=w`$=Wz&GI#U;SD zb#f%B$W5jl5-iYA=d0FqP)opjF@7>JI>L-h2^>bGnazPlL27AbW8!l%s>z7ZKmqmo zfPKzu_k}+}2yK{_o=IbCa`KCSEo)*w7trdTBl9g&QR#>XI?N!jO<1f_d&xRR)at6f zn4QCc;@Gg3lFy*6Mb38}*fJYK)_J^)gUKfXYUNEEV!MQ$2je)L zbV|fl*pVq|qyt+my_oMg=6?^^vc8tlUBA^Uz&5>qh(U`xH6)9K&&98~w{Sm^ObqT_ zd`Rs~mCdnUmsI3!?-+L7qd1zrr&ytzte-EppF075YQ6aD;0Tt`y zFWd&|8Re0<7iggNGO(p{^K^3!?;Rc-Pd~(a&je7ZNUAxr8pL@a9in^oG)SxM^Snnc zE$O#L7i(j)*mjKL*ya^rdl}T~z*Yyh1h`*;?N?y?Zz;F)r-R**?~wU|_UlyP?><>e z`&+;FB@x@a;agNjzC+PK$)79m6WBg#tOpsZB`>Aq#<3sgpkGVyq(a^sSSZS(|( zo?(P+*O4%OhrIQBP{)?3#w3xt3~Y1Ms5Pl{WF6R6N3Nhc@{@pDrYiII!?vsNyKmrN z#-gNj`ZY0dxZ!dOWvYyr)#3tFsjED+SY679CHka?PvY1;gtX@_C~;J<{uNorUy!u@ z?=J$j=k{SB90h7BeT=rHY_tRmyg7A)(m_J*$S4bqY7!pg@;H6`K!7dN|41yPM`Xh_O>Z&s8pS1sol=CWL_J403+m8vOe(|0W zTPM@0e?ZznP2}r1a*d$4xgbozOaf!Z1dSgta`b)@BbgZ!bS$ab=03--TSV#Smk2p6 zh+56UI4Tk>or1tm<(MFelB(C_bYL1I?E;Qpg*9sgwv^Yp+F&Kq~xW2a|X=_3brFrsokG{H&BnQe` zx&TJ>6g3;5Mm4i9BCcUcv1OKl{KX666Ah^|C70J0cRr1xo<@K|BAF^sEnsofE#T2V zK8E1a$4WATL@HXcn@WSD@krB;254KW{Z;P;+IH$F2T!p#H-&wN1yPqpSdS@_bM6=t zc4S6vrN-8z$fJVxVffqxw?je_rOW+L@<*?^{Qzu9jKwg$w$U;mqHnr1?)ZH=2DpB> zmiTjSj)f|A#wT#-u?x$&o{CIRdl}d=6`3`*m&v1~{??&1YzeYiiy1ds5wp5+>~N#w zJCgBZwEFV6>0fhR>Fr|tcz^X4f{&kI&%(N61NLphiiC=c+$=fZa|&^nszc;wWvcUf z{hp8s36U7nV3H~9OnzC7tqyFNQvA71$b&RsOK=;regteQHRa{xzQ*z4*fp4P!7=U1 zTI6%`sNm4aw#xlEQo{b&BZ)rkj7|!;VU0OYJRwQc412krJ|{GAOJG7gCx4?{MQ&>c z8y>GnE%_Zb_{_ryGa6|#hy&%%OhrERda>Nj_bHpQ0=GiaS+66$xFn!<&+fs=%gSK34a z)np=YQjx5w*2d1*9Cl1&IJeCr^JD>Na8F}h?j?sHkDJR!PG76%Cixyo{JI^qVo_`o z*t#89_qs%m4P@$OP49qn^q2euG#jLwHPFs&nZTR`QzsisSaf=EIC&q7-bs;UBF_Tz z%~TLY+tb;3`gODohWi7*R2{2Qtv78R_^fW6SzIbot1%(7zV-vSwIgIyk=%bSLiwdY z@c*^X>nX*b`})W9$JbQkFN`{84d3HS+OJcEb&{vw`}+B;$ON|K;ctHdY)>9(z?OzG zn1ZSR><3eYTQcD!V`{1fhI=A4EeB@@VyuNlvgbP#O{(S1iX2J@wge`O+OpP`wY4OY zVjA*?h^?x@6<}-sQBvg&r%gaHEGdl2FjwTf%G1dcU2A>C-b^D@fbD>_Gie;T2yBOt zHT_K@wmJJ>khXnU#8!aqDfI~{rPD{dGmwK=4hb3?v{qa@o zk-r4k#;xBXVgKd=*q(U}$S=Q8^{hfGL#Kp>UU&lVemI0gG-9qZ?!+3*3P5>;wfEx5 z51WSJcbd?T90NTCY$bN01KVCl>TBg>y@*Crkw#-TE#?t_d>sn{-@3-1;}9?AKMq z)@49xeI97Ba$KckN#bu$4~OY&^K}?)Yh*>Z0WRMjk^vQRgxO-Mfp5vh^ife z*Jmnn6^MoJd@Wd1XvtC6TseydTGG&-im`o~5Qeeq0-*ivFfd89bs=?oyW zr~0qgKtXG{HBf?K|F9{Zic@VSOX zFOv~lG8Z#y`zv6}2#F4CxqfxvDn_1O4?wOJ&G_R$GAA{a$L_=gST9d4Te2b(yb9y7 zll8TCg@u_>Tc#uv%<7EEjMfHO^XnW@EYBLSjf-BV2OUX8F01r*8qk`tsf=lbB{aM9 z;%Bn&)Y}L>d5Qz8Ni<*gEVq@$u*mu_6Qhi1T%AW~r{T>gt91awjYF(ssluC7?<5aMg=J?XKEagnqJ*r&SjSga~ zJ2>*(!+~WChvPFsHYm)z>=Zd)^fON@SrFnawWdjrDZp096U*419mC$JRam=&E-MIN zRa0b81i9?5e*|n}W*1^+YN>j0GCqss<_`K*vKm~N1TuUoWT4$A$5UT8@-@j68b~cI zJu&vuYhG$EVCQ+8dNhs<*K}ejoehQG~3sNIf9Q zWJ^G(07l*%&jZ<8RM)Zlm?0pDl6@q=wuNRSjIDdKSa&-`La2VU4>W6<1W`*;$@wWZ z*}`=|Dz7XXVXAyv7@7U+OIUWeaX3DQjfoklv1LcF#$Ns1-v+iMyXN1Je_9=^jZR{l z`;^6rfXOB`wIb`IgIg^nIcOrNB^di-fYtw;>wYev)j#*g^#A{2o#of|`F)Tx{taK! z2(-SWeQCtDH1rLMBPtcy=eULA`yQYeQCgB@tCW0NZDW&NSDl~)Ln>Az$B(2g_Kvr3 z>b!%f=|>bS-=k#sD@vws1mNb(A0oE8q>o}iCYh8Xj#7kD3e+;1%P4Qy{x|qNKjC0% z2*?K%D>7w$H2aO4xH5?JR790rtD-CfY&D>k#-VdqYHahCt0-IkhP?H!$XNfP)c}89 zDl&oX!0!hrAkQdcSJl0-N5p_(ei;o9-ddLclEyL9eyP2dMd&4g?T7$df?Hj}=kG;q z8L8D<%JLK9*6$$T*8GE{BA>Yp$jmj7CQi-Wm1rpX4CE71pL5`tkT_E_%iT1w7CZkWb@m%q#bmu?`8bSi*i4apzC}@e$jk?J8pCACR%#MAUjm zWF{!NMBqh>Re>r-d-PmSZJyIBPREiCvKYB+=23e27*RXPYb-c+SY=EH16I#A1-J@3 zQe~ZR{%XLM?iJnv!Mi*s zQ3H{OgfsZeU7%b*^>81D<6iizMv=z}TNQ8&xbDL58WK&+h{Yt5KT&EZT21gf32qGn z$XHVwa4BYFrZN8_6`3+5+=FQ#vdg)jaLl;viOHxIG}Ctl%+oPMBQ_HI1+W#sY^P4H zY6O1-uLQURy-LTHTDAnhcZJM~_Y@*4vIcCEb~pTXH@f>YVoLxe)%4H~2VNt$;(h7c zi~u#x4c>R7gYdH_paUT4Fkshw>%xJfv^*Jw(xTIx?pj#_M^Jz*iN8dXQ~}$AY1RsU zzTD660k#~k-)=S}%u4b_fx{0GTY_CxW2>AlEWaQlESg$@JOOP_E8CEhlrw*T9`m{h zRL@h`bI;(2WH|0o1b=>u9_4UE@Afhf()I({k5#>)%oFaT!ZO!EbN?7e<5TcCJqUW; zIJFtUl=+~@QvJEWmV|N}4mgD)(iT3AQirs|YXpq3F0ZdRmP z&!fG&3~IZ^jNhYb{T}6!|AVUG8ZNqw%l|F66Io_^>u#aQVM4;?|(6{P1wE{aGNk) zLEO#=kpZdKPvn_dFQ{Ul+UdeWi#I3fJFFdK9FI-{9`tkoWHDHNf00giYPSKgQ>n3~ z;FAC!Ih>STp<5j^`UTXI*o44<5tu>}k^9qNol;=bf_<_gr_X^-Mf6EIZXzwHr9-O} zXZ;k^?H2-?7LZON;PFbjVAe8%jOm6Di^Uw*{vQCg*TAvM*={3g8J5(*%Hq5@2Dq;D zN-5f2GIm^kWc3wuh%<`cAme2PsOC_3PGD<8%wZQ6R8&%;0m^zMa@dN|%Q?WN8&Mjt zWtM}0L`w7&GXmDOEoSVv9XNh+Uz{;Q3?}o1b4HI`YKFD|NoBi8l$nMl?<;zaV~<;a zt#8ze0)cxqs{v9K0ae%HEK-%MbhxN!hBo17P}NI_zk3GXI2lWaaOfFAJ018?qe%mf zId1wK)$AxW<=KI}XQm<-fm$AGGh^7WSm5)FBKrJ=FxW~>s}P{*uv+Qi%3S9j!$=tS zL^>J>!ty!PcDHftaZ2rC(ruE+`?=#5PThAUgM|Q=U{(i6tbb-U#HmB+-YU7D-vG9S zjF7GI8Hic=2%HP@UL(N~=M|+tBqB{?zk~K!0DF_;60tpV8YL1;&`N^2m`#Ca0%{?z zawtH{pAp~^=rVfDC^Eqh0btBzMv4Zb-HA3?k*hf|N>wyjGd^WP(a_}l)TS7}(7K-W zroktV1lW>XYu|bYsHW6@!9J%Gga$aDQv{h^*W6Phnnm{ay-HEY371+j2HY80B zu+EkMh|y1GN-(XNk-bAVBerC5R_Xhcun`?kLHo>nP_kJZRDG^fmsV1h&*Ru}PQd4$ z!j8*>^S7_iNo$Tl$r?~v&H5S?ehJngGp&?;t^?aj6Rq7N_{OH-cX<)^dPIWi-v!um z-K;t+$gaE>2c|^*nAy}9*O-39s5zv~3-v~&a`O-&us!zP2Z8NH#FjeP0-OkJwKS4X z09$b;2ryFFCBBC<2uyi!?zSW1q&Bevt^~H!uRYU%t<+Ti2C(JW6WAtAS~{|4LZYt7 zXH}G*3qpY2hh1C&TP@0J*OhptwoDyoUmy?ghsGB zj%n<*#Sm|8%_Hczh4{!fXxM&0dFa1THU34SwyMrn2et&Y*9DwJ?N`7?24n(VrDb~s z8OskKXbU;MgWq!n+hf;(IJMw17uuD~xRXsz-{|E2l)X+|Dda9yl3GQuK71Q#he_mq z>c*dhuqtQz_KScm(+msS8|anD%}nUWnn$%2%dXD4GJ4?qJ*iz3FlhILTRjBBR znhneZp~5H29N1_G5xBE1HiyugM>rZcA~-sPeeV!*p#wD9Tz@*qR&$7f0X`zlF%{%g z&H(;ix0XY{ki^268{1B|7*zgy4}fG+NTtM4M{uUq5vxdpb}>O(;u%tFJDov&b5lTj zz&wJq+bmAPQ^!pNJa;6j>~k4J%Qj-MAY!p0XtPK*1X)*OR-+I!vCfte)XNcDvLZK< zA#oOQKVudvvqJc6B)y>+279U{RC#SQ=v3kp_gW~Q9Aa-;)z~r>nb#$7rSpU>VI7gk zu!`jJy=weDf?a}I>faI+i#D$YY)`Cqv^Lg(Vp_?2NJftaG6Z!KkceAD^*s{&bw$O{Ajhvw#`fyig;?kmb3bjVJtFDOx@*~RI3VbUvoMBbYPn{ z5yU7mArdit0Je440 z#E#2_!0TsdCC`8!qghIKoZwHgHZ%rV(J|H|f|B9U2Qo!eR=08B9F=H$*yF~z)rg4G zjB~3ZDf_chk;x={ynCmGWJkX zkvAP)wERBw>P6AHm3`?Gz?ORrfgkq>iTO2Z!Ygn%JAtz)4}u=YZvtE1cfe_t)N=v8 zj1FowwtS_NgAR|h(S?}Ri&NJ)k_!tMWJ#XL@n?iou~sYBq~_eanDBgPI?uRfQiv~5 z;%rO+8&i^dJ|Dp7FV~)|Kdza}?ZbX5bA^O>w1e_Fkcf-`GH4yc>G*xgHfwh~3fQu1 zwLT^YWxue0sADVq3|!ybhwDY;PWJJB+#|qt!{b73a}CI6wEa_&f2n;}?ZYyTVks~M zoYy0-M-AOv9Km<5WuBACc*i}CcJLhND~A3HV5{94_d#Xbsq6CoWIi+-LMXRpv%}|b zB5Zfye0W3wTay7HlZx7Y1-AccAgKe?&wc$@-;cW9S77^v!1m81jv}GdKc9-s+TCx# z+TN7$2P8(WAZEIOfaSIr9D5UPAQ4h*rra!OXozRP?sS6?A& z{|U*V|BI&mZzv7_7s|%JNOUw~xg`5@5vjd`xQ)P8N&6^Z`vKf0tXB}W{|LY9D)!tr zfY2r+^^k_Fq~2*p5I1A)aBPgy@R6VxOD`f*=Lq~Mp+e?b z>V&rP7$p2SnswpaeMbNqQ<0g1{4tPabTVVU{;NiRn*O0c{#i{8o5)bEq zcu=C~>hL3QWwb+!Yzxz<7J(HbiQe2CkT^s2)l&ovLz4D;?r|W!@)n(3R7KZ#u<^Ob z>e=Gq%rk}VUCoTjTnRufpStyLsedRx+(6Ry z@vHhBCDX&7e`vb)u&M!O9q{c787Co((tp>gh{E*W&)9AuX}pGlZ3G$X2+mC-C_H-t zgw93MMCOo03OT>E@zc`B6*n(Kcua9D0)+&UkM4=V6>>Xp=yf7>u#QSG@gXIh*U&y9 zs87<+^l!A(Jk7<0@M+Ct!1>fTj>p_Mn47>Ley-*T4JC;h(IC_J0j5lYle|eO&(Z*rv_amm)cvM#{^|kt z#|=0qupPaFjBgF?dPa->a<9@@Pc*=;Zw)llR)epTmp8u}L5h zP<4Ld(4!H@wam4nrF$~Pm-C)cL#BDQNMaO6cWp`ZqtDGl0&K}{eP+LjGtV7KMP@y% z$o^POAh;#44cJW*IZIfK0x}6O2`C9H8A)Xt@5liS!-09ccKE&?_@LLF*Tu z4ZViA6r}`&=f#CnMvF$*8$ck0Er%N?W0Tl*I&t>m5xTK}avHLqBpOM#5BG7pHz<#y zr~)N=*Wvu^0-*$o@0PGB#{v_v*fJN&Ks6vq%ue?t|Kt<00(9d)(uwF zx3&ckO7?}mR>jFoPYL%2jseq@*(hPq2C`Wo5y#P}O4klKY?Apx;HskWsv{k`}kN-J zm)SuoGA(OakgeADJUcjtyEQbz0R&&Y!0E&^4(wj6TI?wA?+SPxXeA+HPtne}lnKJ^ zL9WZcK^rSykVy9GhzWk112Kma!4Va)C8*_`4_GV+Sgi0{?C@Kh@~U)L{}^!fHDddF z!0sQ@_y0?Q90HxM?eqG8K=HQ-oPOW;2{8X#n@Iz;rYktN--OS08$SD8P`k}H=0fP{ zeTdd1Sr`c-X)yIlK)(R=D2b5)IvJpu2GT(wdsY@*-2OeHj_>7_k=V5LJ82o~Rb(tTq-8BPkT>4|U)jX?cMc(ByNx5$4PisAF24bi zAqCoUX;t4^Z31jHrqk9`jYhcy6iZ0YFW`7;68jD-&OBC;389u_%yk6`+jq!2zDLpi zEpqm6ka2v6r2Ts&9BhA+M%LP_;~H}IYslJuLe_Fs*qRA=Bla7J&W@w7_%jeZ1qvyk zlm&_@B{pBq38|K_SyFsH9RtFr=xnbd{p2Bn9vZnnA?CP>wBwd&nU>6VQ8wK{*>D@h z;p-@yZlY}d2}R2lX=U>jd0#PIm$d4H@dgr>JIGt_B5l5fpz#LI+#^W6nnUAY1z`GG zIw35gNM|7FPz15vG|)=})i@CIp}o6^+?zQ>XB{~A7=&1c^?}DzHl!Dy15rj>DV4ChWV7IG!6req#Y3aN?m%5+9OQ zQH^-OLztSw73Cun_McaXNT0+Unlxm=Rcd@$z1>63d%Z7!ijrwPZ2V1)ZZHxG0)hfO1k zel-o0qCh@~=-c}U%sLTp8*uJ1ikuP2St9SAq7(E1m4aF$)X3$%G;->d?+IqREg{Xx z`u1@8?kVJpBYSj{0sXA5#RtZ@3M)1h532c*=5lIhbZL5;mVU6nuPFz+=2QRL! zsP$W6w1kEu!9Uka{=!j)4!_QzlQ~6t^Jkntm=Mw^g4YC7o?Qm1o8{a%pD@cDIkDbG z#CA(aqol^xZV>06iXs~kHydzv`v$Tu3ldI?=%0o>ZbT-hP? zdL^dUH-+E^%??nipcRZDxxR+O$4^9KnR>YF%TG4~+TZ$_BE~9s+(?*Ah>nbadc9dY zfvN#<(+JWwGm(c~CX%ybC)fpSKz znMM(VP8rQs35{kEohJ9sxTVrx<|=Vn1%IIdw=RjD%=x5yJ?gMuSAH{$&svl+!v6SSESHXG%4l13vU zCNunFZmfB&SebOdH~$p5;1Rmq+qx`Ssj1XgI?^Q4NkCXfw^2g9l13{VN8O^0QmvO-QI%xyJm%icv$RO2X9m^)03ZNKL_t&#S^$z6krIr&c!ty22^=}C*teOm z@3J9qZw95cRUjHvj>bCoOr8ljRU*Lifvu7OQc)mqgwpDJM4vvw>BKlr+^m&%;?U*9 z`O5&FKw-b9C>-x9S-55nomLL*b{^es8U1ciIXYSAj0$SusPTPt*K)tR|LCs!3XkD&7NBF;vqaAI~KXm!f?1&wB$nF(es zII-%@iW932ZhsH(`uaNx{Qqb5!&hMY#en|zf!E&xzyGa(_9Fnz+P;KqNQ|&E(`^Kd zcSPoeN{|=AWSWbP`F=T?Fs` z1@SxoAIj#xqGI_5Im7=JP)h(AaeOb0;Fc`DY1?0rv3?^!F>AR7w!E25f!n-*gquhh zZwZJY*+|T5Lwwqc)RQ^X7G9ydvxfTS7AjjiC~t3~yt9tV_A2UI%jm8z1FOr(+?xYy zMSV2VoFfQ1ZzJZsj*J;_jM=e*XsL^?4LG-y^s6UivP*zJS8U0!Ro{UwVhy>lY|Km_yp@ zL5zl^^Ex87zey@~)_MyC<6Y$L-jr4{-bTT60|oO{NX$(_q!JuvVT5Jm=iF<<>4XdZnK1+&&q_LKerE-_gB4_sSCKv5 zK=ybG`GZXq_cl=7T9UsPnzZ4}ej8`3A!bz7IV35S5%Z9M0oDzE4yfg42y7WK&D(FI z;JS;Vdk6&=Q`Ta|#5Ynb0 zM2$C*aNI@Qbqg`)O+=+8_$Cspr`6IznI0Oq-a^cB9R$D;>ovsOw~(H-q4a7FovlSQ zwpUQu-9U+LZw-~*6;yYZQQBWbWc@XQi%$@IF^TgzJ3?MH$HO)yCF6J7a56oH;EP8{ zuPjI;uXTEe`oSi0>+@(Gt)Y3ij>hgfN-IlUPXL=8L_ROkz9R)-1}$nPmrDY7S8yL9uvY| z<>)w>@FMi|F|w;GNUyIVx3+@(#xe@)i_-XYc4HOkwH1VZev6YQ4{$s?j=;1Fp>eZl zWglCvNUHD2j05o(_mN+EE7wV`t|GCqjm+*L(mMx8Z|@tsZx0jLJT|#i<4US*WVt>YgbGI2ew-p)l2w0a+fa|y2#j$e;{!t?W zqb8}N4ZH3LQ*zKggmdOxe~H7HSuujQ82NUZ|1Nm_`@nWYWr0{M z$lL7#Yzb=FQdSdEcB42RB&yDF`UvDw<2T|WbU6{9 zn?df~TVeh!?(QPDw~y@JA+m=)#CHx6S>Hu`Z5yeTO+;S469S|Imse`PrO#Y09JyTx z&CVdh^J8fq<&7m2w%3r^+d|@C2g$=-WRCZdKio%QX9xMERpj3MjNtez=(r&RELp7+ zF1LVLzttdF1B@{K0^I&XV5_qOD`3ldenzU}RvQv_tGtpZEoe3gsAa8cz-^J5Rh|h6 zmlIj119__hX{#OVAIfBHxvkinn}GlAGX&S)BeuJa=z5{8w;{#+4_mJ4#LU?Np zf%W$|U;G(o({ng9*>E^Q$BPSoqZ0wM8}W(z$UT0E`qBo%i2n|mm2 z>>$6ei2Tbp$liN`gm+3(hoc5N!UjzW#$m^ajbv{oaYR$jiw>W(VFXzdGZ{uemUBjL z*;q@@tPIxEGm@WSpBwE0v@(-ZC_Q_M(!v`Q*XCv2*8TgaoE)Nje1ziR5%N2SNUv@o z`EC*MXD<<+ok3`nwe2>!51-8fzlU>S4)N#zKYQQ7-o}+Jxj%h(#>!$2h@BgWNs@yk zXM1c#iWz~(kvV4)AX)p>x!okCv1i8id%NGW<@xS32vA^$+qX}hQ>W@VcBfuRoUt?g z0vx;3FR(xLLe{Rs$rsrC{wu6L{~Yy+Q50hia)yqqu3=HvWIJa@QG7Ip=0Cp1^3+Q# zrQf2Jn?@t^4vo1tSekx~&8gQooSwwq+ZSkk`xKc+aZHcdNIyy-Z97tFCDol)M2+X) zVEw0;*m(U8Ym-yh&*ZS3&S7UhD`R&qi}klNsDJkY#m~RQtQ!+m>|82^;-d-7CSoA9 zIrC@&#ph44HTf1Blkc!GIgRyq)8IO=_Ksr?8VF8nadiX(NC|jbjMql#ZM;j6&ogsua=+-@?9r8++Q{ zu^IW_UbXfEV5{E}P)lIDuHD0${y>4nC;^-|1mt#!s7@o;g<7~5OLhqLn1;L=lIn7K z)JDPKLLWvx7DPT4Kp_^8zSX8Rge7ALn+#5d`mi486Ck(~dWikVU7TunrT2GTSJm03 zbq6*39%}A=RNRNC#(HEl-F^WkOI9}sbO?HU;6o2p2JCrbP^>!`s1?UeEKb-+kC~WD zX_$^Pc+*iFwM0azXav9{LOrYmTPT23*Y2W4aBmIE{;q}w!LdalC{k6~3rdh>J`})3 zP{oShMsx^k#xUsZx)JKeR`?;-!uQaK+(XgolByQ{d-G06yiM!2hDt1o#gQ;(o`f*- zB!JRb5cOmLwZtH*u|8DoE>tbjtRKi&jNC<5yN{gFE9aQUkso(Kn&Vv3MPYmd#gRD5 zNf-6Fjh4dzDlAo~4LvBwQxEo`9PAT|2_^y3j*dCkKyECKxmZ-}6<86>q~b^?V?qa` zO-bGiU@_c-O1MkT4=r(6*RPWU- z1oc)g>UN*>j#r|}l80cGL#WT@11#HJShEO}`>`Au#)=-qiW$a|se)eGsi@KGsnDtl zo~ot|qZRE%E28N5q(8H|+n^`0JB)dA2-9{5lTHM0ov3Uloe-v+0H*B#3Mm`qxP_J# z!CG_}TfqVB4)tPZZ~$9FgQ)ipAwL*EIuJ!hcSKn;7mG{Qp8c~kW)RsC3x$z57AzYx z5d+x>>5B9KG_YyKux2o5jY!W~EoOlLcOl_oCT=2=GLat9F_*G1oiZ_%G%+35G4Dj= z`VsUAcn|hsCESl@bXY2XTvsxN0V-HZ5O29s9WK}w@|G#DsVZAejicZsv8Wjmq%@;J znfFZWYzEb}D{F(wHYdh=%th99kc}mgON}BOPa@+c+QBPO+p;JKrGV{!0&e{t zTcIG6I{P889S%s~PMY3AEQy&^5|d*Iyqs|HYRr)yxAbTNbB|M)dz`>b%EUb9T_}Lf zU=TY)0qh0?Qe|vtK?P2o2pW!#niZBr2uwo{$Zn#+2O{r*Z>S3&z zA-TU7BHc*qgDAu_6h~rMOvW+qvfnO_bUY;^8%rVM#E~^@Vp6WUoCz_kKo5I%OGZ@YOv5(ObR41O5{MOD0~s@lIU|U9 zErhfdL_v$9qD4>(Mo=FLVKty(IiR5tu}~rPTINqou6cg!39^YtGIFsAEVyHsvy+&% z;&^A+c&A$^SP5i;h5*`XG=@shMlooi9El+paZrqpA(xyGQKE&B$KXhhJ`r_bDkx_X zDV0DlW2kAaSoAc*mh4ZJYmRA3wKQ#MD8!gJw9vE_i03?^z*L2729sM|2GU14N zO&413;&2$5!7%2-nyizV@o{i}rbk9FlSr!T5KE!zj-X~Igua^z1d)wKP_iwQ?Kp~N z9E(N_88eQIo5Vsqg}LMyW>aHWc=QCb<4-U*{si+ApCbF{b7aOo#f&?S$*7HV#1d64d;H>LD+P%H#3=ZLFD1go35E{cl zlss_D-Z+ko9uiQ?Uch2BfLSAmIcrG3Ud%-dy(F?rL4w)2TFl7ZvS}R9y>JuT(r6I{Rjagz8vydoe%SEu-M{ z2zYBaeOPjPvFvt>KkTwiJDvMzS`Sds?qM->2bu7FWc5B|%|R?!K}m2h$v~@4bGELuA9j->#NsUsT= zA{*{Ug`m&qRmlYHzEn+@^&SN*slcuOesD|r<+2@;N@BwaOGTdnelZq8As$379>9V< zfO)H5gl-rN7L6g4#HTcXr5Jnr9-v`$p=tF=m9EApiF^B9c5RjF-}12`TWz)4>Z4tx8t+dqI~D~=5_hPoL?iK>$k8#6&oz!E{^+t47U^kFb_pSDa1 zE>=<#*i4KGsNL2LY->?$lVWLjb~d*1$Yr3K*M|kbW~~S^wvLQzAn&qbs0rBKwj$Wm zhh;vj4fmoo+>cr~hc(-f8y#&x#NgO-&HiLkW>+1GGlfwI2ayX0gsG7a1&|L8q8y|Z*&tRUL(-?ss(LFJ z6vbcm{IUO!K|1Fn*Es^jjLU%UdXQe9V{fiS0jRK43!7#@l5WdR7(TFN_4Ypjwmvmk zD!U%Ay`nIi5iBQDsJkiTZ36TWOuKQsjyZUlurW23z?5NNQq%C-)bTE1Ny4d;a6u~M z=0E^P!%-XtHEc#TRY5c~p;Z<`VPr$YLJd#5K`gjYNjR}GNUCDlc2Tu#@Z1s15yTPL z%Dhb_kaJ>~Wq_@lDCn#v5%8J^cV`7i|mkw;$Rf5fQB8z#=dD|HyXxvXc$~4 zn9P%&rXh1A7u8YHE!0d)dPJ%Cy=>}O5gPEXQ;mNO(E9K5+%vI2 z+Au|*geGf5vBddn>BxkKQ6lxz)=_ZGtHJrrpSjJLVM(+SAd-H&uIt#;b!BmkAC5^y8ftH>` zHDIF_bkNiiQn}4*G5Ng(GbWT-(q{RZLy~HyjYZRus&-S0VJR9DaLZ%>En|2u%-bfW z?5K=6Ga_J}0KKSdB8bO|Gl4JZ!UT~_x)2cadNoW}tb!_LOcFs96no>C_=lt8=Y%EH z+jnjZZ%p>8CNX7?Asu^!V*D{0v2iq_E><-g>k$*n!yz;WLud|1(Fo|s2UK!!&eFg! zPr9%x+eR=`;$PHqoNyXM0Hd`I(Ab}uwHPR0n{StFRV6tJC+jpCi* zVkT-Kr@L|;D^w|un5Y|;09#(Gn^a`#1pH41Z6Ejj--Ggx!1gZ=Y!CZy;cVaz&ie1+ zu*pJn45Oq^M&@*up^9eN;5;}6Rs8mV`Q07N$OvNIYw+2KorKR1&O6c!c z5C0wO(Q9B!K>HrBjoy;a{hrn}<2G15-Oz4hOS_G2q21n*-edMTu2};T01;HM>R2Ch zQGLYTqdufZyO15>=s_;kgT)m4ar>kKx$Kha*@G>uAA80CHbW1v9qGcZ)r(cDM}TPB z9Y#7HzmYo4KjE6Gn=0k9>f0q@$ zhSM*Dzems`)xBsJT9NzGqsg95_HZs6U096`qGb_RU35ZP!SavIqLx&&~A(HIuu6xd)z)9{9cxuh-C z8)nm4@nf}Ek`n~BR*&>@OXb$=6JTG|`mv}F2t$I~yxxnF){RoMR}^bW{aay$E-;Aw z!G0VL_2DQGz%HqB!4MV$5iCS4$-Xa+K1OX#90ZoktI0eh`Y#;I+sXDpJ64Q04qYIf3Ao7up4{`s+$Yr zB+w^)=?7*Idv*jH`Y>AIKGcI0_Zkw~H!1sT;Q?%g`{j4{Lj%|i4hnUYy^^c6v@ybx zps5%^RBS~(EZQMa_AWVLaLD^qKDHx5LnSyOlZ2p_TfbWSuPDejKl4GB5;sy6TLHFI zNoEku>PW;w(HTQ|!Kx8vB0Iylwh zIE+|WjWW<<|2%uJqj;0h1QfH^Z7LSSjN@Y3v@yfr-L*s*ivWm8sZz|8 zDi8y7UOR#nb-iq)6E4zmR#`cc$imXEKF-qmoq6Ol*>FOHWhNM#Hv+ z4ZwNKb3!IUH90PQp;a@9mX*Z1Gm0%ch0SP8fZn#|V#kc571B{045JXz#ImOlAHm|t z7|Np)Ah2yYD)~`y67o5LTG4bRImABLmhDLYC#&v@(SGEuK@<|hlDzvPz_w)CVg>fr z(J`BFkRKmGVPX^uBXP{8T+B@*@ov<`yNNhvCK8w$aq-SEKnnRR!A69As4mt623jFg zl5dsRsE8V|%F4BB-Wioj?PB~9@`=abcEKGHurs6E$g?sXb;K{W8HuAjXrMmC`JNP7 zal=T0=eKMoB(X;dec6nOpp$@2&P~&nzRY^qL@i*VI&7d2(2)*lSa2M%m70Atg83(7 zQen-EjUby$A{&njbA|U@c048b9@jAfVX{$jhK-t&L_xEWiQ34z31mjcF#BWz(_cKs z-1E<{@Z_;qA)Uax!~~{d6PR|!u|NEEIxKVJi7Owgk5_qMB5y2@c6f`Un#Loaf*pu>A`I+l}CD>M&K3348_ETAv7rTGv0phW?2MY;Q~Dmi9jcgQdV-C%zm&n(9GBI%07v;PmY*e1iL;`psL2At>;QJ2xY+r69LP=M zqBsYX7XYgEHWqAmI;+gw zk{T?^%)xtD58T5}NC{l+MY^#a?Zu|aKE6Q|%pugDB(VSX2Xyi?GEm~Vp9d56mw{o zGw4*ZK&=SQr~TJ&P=EATDt0Y`2|a>MZ5W%;J`r@I!ZZIass42=prvZ=-TwwK9 zC*6<t zi|CZ{*m?I_{7-Xnf~*+Rhe2k808b{2V&NlL%3zh)&_Pb)I)olm2ah)(678r)m-Q#|DL7${tWEcfSn`NMAbd zW7JAOo%d}8molojY^cHa&K4K2Klw9Oo_&UL+!3*wS}=s=a8!V8ZEzU;ncl_h=VsMR z(LqhH;>oHPt9ngc(S=u{rX(R)p<9dE*tFt8tIUO>D92M+`}$iPzMDcjo5f|J0OS^d zTmdMRfimYs3CO0=nVQ1ctCy(6V~PP`YHF>Zh?o;V-c=sUe+1a(EgN&ANi2T-O#0zZ z^I5rHPm4JmE~c?pNaM6smT}T7VLzY7+S^yCef1@B;}b#wCKIE?Hi@7nVs&fZ|A_tB z8Jy(vV(D~Itpl|tP;bfhvRK7&Hjmxe1?;_@LOwoG6qTP;*<*+Li z*rvz$5IQ&S1I<+8P@0LlrTl4G;j0C7)Q1dI0;Dz@k_?Cr9C!U`EMc3ddGl`p=Qe&h3U1D(bajvFl*ouySA<}0|Y zG=XXpo%t*_etd!2XHStIpFkm=6#BMQxwV*7m!;2{io=>MqiiRoAHS%_1hn!x)wDPo z(Kzan7?@1pSn?PK^C1Isx`W0SUt#;j8&LLGGzDCJ#a$&J<*Oo7t(c(pBe4B*f?8htkHGdX3~X1!x3L`l8&9TiMJXcFrshh$)>lW~2HLyI%W$KGgXtG&JaL59%8J@r^e$S#|07kl4}mSI zvI^MV78){Dh)GGlS+OM@nc$D~%u?VE7KUz%VlT3jN&)bgwlegEqv`nuaIpoP@4P?S zTiD4>A^&Uw^NuFMC5w)M@qiqqMb zSo$I*{b;Nl3pLq#h*kR@*6sV)Fxe}7Px@Rp!uP;IL9ETleR;hZxr=S>J~s8cLb+av z-jSZ!YV;vURbF{Ej!t$O*!4UjDc3LOnCE(1DWGy+j;PRj1nlqPV(v8#znYMW_FCW` zwgb1Z6Q=6)ZLn%f5Xj0fEshQ%UD#(2GwI;YZ4t`i=K{hB1fuuloNsG)v7_I^u6YmZ z!M_Q(<@MOqm2j4CcO+`Rb|02weOR`8(4_Zp^&wBCU{tMLr71=u+1a^RgBM%adNnYqoXZc&};be z0PVw7fIgz zq?ep_F0FV7Yq20!YzixNVKMvwX>$Oj&y(0szXA4^)b-|h20d7*_RIZJ`=(TvserjH zL1p>-XP6%`g&IzuSSExvbfpHq5~0u+lOJ7Z==adH?qMbN0Cj`?{dcA1fS>VqXsJa7 z@%6}{RG=y3MZnb52ISl^3B#f6V${}uPl=TcO5ZSF6V&^F)fbQ=sO9)~ROAnVt@<0P z)qs7FRQ%m|{tV~Sb3khy*gODssd~$ELiKm5WK%hsRyp+lJP>u$gT*;4KYc3R&sE)( zDoP!$DLX8>N_y z%ETD>J~mg>n$+1=&k3sM`##qGmhy{ ziM`3!O39dtth{fjicQ5~D!rcigI@1c+Fb`qdF=l51DdI%wC@ni5{Rsu2G(p7>#nT? z106-DCioB=8R=8hRgb2wte_~!M7lMtc_`jSI&5iT0$ZE{z#84TL@}DeUF_=PN}T750%>VRwFU2gl#NG2nszQ8`aT_sIe5%(Bcr! zQ>CK2M1d{ouT|7!R#m~;s12$H$zc7d5=U?EB zVPVR!rB^gJGA^P@=aq_B?8vnf%O+YT9;@%A^_p*ALq+iQb*%pI9V+7~#dG<3F&;1PNUv#8Qj4Ka`U9 z?7C=|#Qmam;lTk;n+>eYOkw`{Gfc)*g>)(Eprtur0)Yv%s?J1%qH?pxyBO9*)XA^z zHlr%xute%`)RYP{StO*_zos3})2BFN;%;Y0S*vj$`1fUamUlc){F$E}9HPCLNAbyL zmO@?FTUKuss8v0<>a#yDxce(tqdx-Mzc8>}3Eu{*cManfirQ_Y%?Btx zHn21E1F%zv_)K0NiRT^-?780$#D_SwXIk#j1R9`v~L0G7X%han%R^lv)_c2|IzpRhe@gH&Mt zy?ujpR;mcI5^_(d&#Z2dzPTH^i>=6Qu{vTxfgq9novgSDJ(|_s$bIqoRY06zTmkZJ z^C5Q39Cmmhgh;6V#Vo}ZAE*4<Emg7) z-o6H!OTZ}u{S)B$5EtzuoL?%3-6PIz8otuwkDv3LAD`khlNS%ad3zA^P9KU-9PG`! zP=0~*C-iMM__{-nLC!O8u1Np`Wqq)+0!+Tb%2*s!re)=pO3ehWtDfrhazt5)&`yM} zNvkCtmtMZCfYGL_WCxU$l?TX3H=K1tILy8S_SR$`wJ(lw(B2ofOZs1)TpWlGCSRYm z50zaA_wDoq2bl$A#*&~w5-U6nXHY;#jnr$q7e!|fC3i@CnCZpLpV>#8c7~)MIb)JO z-HVFZhhp>r7PSXhbo!8cY@qt{XET2hi(t*u1*uRyO4 zem~qQFg7eeS}OCV0=6Y9B#Ag=(!dIBxlWX|8Es0qJ~5!Cza;0>BCHuqWb(9b_zL_aN+qpJ3)J&$t2HvmL9S6y7uj)xxVmkG-}xT`5$PE zq>zh*k&Z^N_w$dC(M!u*KGo4CM`}jMEyMdEQPsI9ob|= zs)kj&SFTyzr3l{x6wPh{ywyZdQD*HSl-vNS>}QV!B%vZY1D@7^pB(tDpq9T+U`v6w zCEh<;5Od)nuzg^E@+Gjo44e{>(Q1bGujkQxK`&0vTa|vC1d*q-mRrX~E{(NkPbE;V z(HB<)gp>!c^zUjB5uze!WluLnl-Q?D5hrdrSV5&25j|1!zOF?oj`|N@8yAIQCYh$HM>9%2vs;%KYeT2!LA6-I77&W>IgBYFG|u>4-`SR?tb-_AMw_bh^;NY7iKpuc&Ly!y zP~|-nxYqO8z+>Y*v$BNxPe0*pJdU@fjrrsVmcRWG=lQa-^zrWB%g!+_8CUWCJwL{A z=Llz9=Q!V(bUNP0NhyQsSD#{<8U_xl_6`oY@ftbO^fgCB(P z6Zo-$TAq_&m%>fW;NPWcNDxcvF#!~NIo}7iccn_`11eTF{p#jgnD#1N5@0e&pG!m( zsO=EY?nyw_Mn~c>`nJo9Gx55Ygd_dH!T;mKW`7$Q#}*-lMbp9>{p61KRd$(+qh$ZQ zpsuaHLj`zz?@VQ538as=a6J7IS^8hn;=%0qDnSaIQ{9<9x2)2#k5_tmLkeuNV!Ew8 zl>SKqT6IncKD*I$DdrIdwwIK*C?DVg@fh-VJRm~DdhQ%S);YkWDjzbeCTz7ttcNP2 zd&Z#9j#=p@#h5}%tWuE@yeFQx+z(cl?_t$qPc2o32V}6%&9}1I(7UloK_l(q)!=&^ z{_jw&xo-EO=BRDc?#A`t`+X9;&N+jad*lF{RjEKq9K2akxKX2v3uE0^rk*RJ1amKE^^KjQLnUvX31#KY1^3&TudQW&wTS_$C@j-Lh}B(P z`JiTE5nyXs%@GEbyn`wI!e9RD4?Xop2=bq}$ zC3_G>XIOz-PuNVTjqWhAv49Lx_W64RA*`;JV}n?5`|)lxjP=aV!1+2ZFZXeYjykup zPyWs4&vSw+t}h%N@t$1z`Wr09EabHzW%EK+Vh(#q0C(BxLCJl9QtZzA!+n6V(+>O){qSef zX;me-UjQ^K#q8}(#|&VDp1`d7vnte)092AJvKDZCRzdy=PH==HNj^#ierFStZVYp7 z0<(!x6n^+osxnO4@SHPv=JphAw7HmYt&}wdYAb7JTM~Qi^a3i$q*79KV?cI6`EasI ze4+M1k`L$f4(6QaxK#6>Ae!@@mBphSRKET~`p#=9_JER>JgBZ4=N0GD)!Z6J-U*=K z2E_xJKFCb4aF8v)QDZXaU-;DiyU&E)uMJC2Z&444>Mg~N&Wl-9p=DBq`~KcDP|aA* zT0Rpm!F!z*aDv+n)SrJYB6t)>qZk>jaAfH0zxIZ%-s64CHHgQ_>&@5xp#L|MO0$lJ zH?EG>>z|c3DM9Te@7fLy(7_JQu`c5hn>fdgq@B;@s^Ws)%?DzKN0o32e3dm_d~DZU zS47;nkH1$uiYnFg*X|Jfb3QT_ka4Dx%2!V>CM&&%Gpm|sr{ZJ!GBqka-LuI!HtF@t zL%w20U&{G`&5__FOx~UAtgC6f}P13<((^4UY@6p#8Dl261Jsmz^6V_+58*oIZtNB z23oJb#q5ZMbWB6erDD7iwW8pj4{QlyKOF3@W`8Z&0sfYvT@;Wab$RKt&w&GaD0_)= zxo3Ib0+*L+@EAM%oS!lA#b@Qw2@VTo%p^ypm;0v2F_p6YQD#rSCsrkYKdO|XSxM&L zdsJAba3Oox-^CsL7_)%=O_fl(;Ji`m(<#nza%1pkUJqG!m~1AKVs9T5tjcN*ikgj5 zSib_Y)kqXFJfQm#*#5Zz{YPN?7YDXf9%g?gEmbncfLL2#rKu`T3{oyUe5jUMiGMC| ziOb7#8S)E!un}NY7Ep+>M@<1+(v3+;Cb%V_RsE-a#rC#T1=k}FvCe+EFvmmCvW7xP zYhv-zErCzk4v3f!wwu7^A!-jm>Am|3$nY4wB)k{%OYBJe$SkH*MOe8z*}>tA0=5-{RuBZXRBL{qgqPUQr_qzw z_u^GvvpbPq)oZE|6p}Le;OcxZNN%_RWaD9AhahBEf>kcuhd2jA1_g6fO2Lmk2~Ff; zoE-}Nun@DvmSfupVm+w(GYOid7gp?n`mi1CgW8vF5rm>m&5|)7l`B@S-UqnXAlC=7 z+^!nEVnL*Ai29ToFsm+huXwdCv8qMSR*Mz20SVe>oFL{O$AQhJBtck7Ct&A;ih(t^ z%w4lK%E8MhaEE~z838M0%*Ml_E?lyQQHu6U58jd$6mZL9@ImZv0k#Y#vD8$w%+5K^ zPtOz+%p=8;m%w@xuK~}yAh6SORW0Ay$NXnc6tHy%vG61YY&C!msby^mczB;M@ZlWt zhcF6QY$sCYMLawO>J1Uxp~@;1rs;`E;Ux+!U4vTsCq^YG^TF*(RH?dB*>x=vP}Euv z@G_`pV2sUW;P}9+IC$B237ll_q+Z8!uI8CK#>=BNuy=^*u~E#&Y~<~T@__cL!OCMb zAd20rxN#7auxiU7orBkjzejp4#l|WEYzGC{u4Y~e1)T{F`H$y91|uqesCZG~w@WoC zc2BVK)wd`*v@s!=r;QZ_ohbGcK-u;{5&^990A=@{8hkCFmdfG;{ljuR3Rv}ns_4Hu z%x(p232sfLwl3=%tGWLLz}5$~q?`Nf0|HxGbWzkx+9VG5&}oyILLf>gb>RV0CLIY& znVe|j&|3Ny)ZCe71!2Fo^{11 z;JN2x=6Vp^wsC&Jirqf2w}I-HPsLh_)++RfC2$mvQ!fE^1#Z2cIS1u9E#6NQ3=2VM z=ypT|?PeWafNkRqfi2H@Tar_p1N*p;298Yt>j1cAQ-@0XdWnU@W9&_*k)`6TNBv~a z<%San?PLB3uuT)#9+G*ZR&2GPb#TGt*(K)}K?&D)f>S1DJ2+=`vwep1wGI3{GL9)y zP?K?Nzk92WuYHJ%iz5)4`@r^0{=NE6ez&><2qXz+wz2;D73LBtQQ|E*DN)8{&n&62 z>?fslmDuk{qCpb{Y${>{B{2V8hSStS=0s8zt0aE|9nD%?j~ z?*UsrBWQ<4P)mCxf=VCI`mcSUNq{N9l9YA=Owz6$dg7|rtV56W8y zWXoy9&-uPQug-vjQ=H~1m`jX`s{KtM%hv?7{wVn>%&agIWZ$4oSJ`iFXhQ#|{oggP zWo*VIGv^TRJ+(%0ol--+$CXc#{XFMqXOcLWb&_I}RE)X;Y-=GygtC4O*!~%-l^>7k zV~;J?|H8m_J#<&9imO2a+a6?$A!HvV6%C6Eg&*V)`1ykioj({5F)}69lG*J_Mto#% z0$U&4vO?((MMd_3Z8z4#w5y?_ZZ~#<-QrKV7U~v%PX?h2P6%&PrT{pG6|DD>u(a(3 z8L|NTz?NIG>LgYsg^Yb@bqQz*dg{gicD|kfPT8NkB@bbFI5D2)Kk|x2Qfy-)mQ);8 zrr9ra<^$W1&_)GJ89kn&ux?+C@TSE`-tX=Mdls@NW|&BUX? zF8duBt}qxN(7P1C;T_V|^M94nKgs~pz5y2*@Dw(89_hVHb5bs+N z0n(Hr^pf3&7AMeIq0b6F}FM!>B%zjQ_8^!z;ux&}OKSJ*GtYrn^!UXs zqe;JfzT3v?m*0zbVlAvJTBx2|=OEZIhs6ihufEcTNexwzrAO=)b=3$-)zlZ+k?KCa;x0ymeG9TKt|9;9wv1FTWDyUiSF02bD<~nM<5c zGE~BXNehma9u>9ftE~}MKg*V$!N0$1%YRE>WvXE_p~U1My}2o92DT8K9n1M8BvS#k z0yczkJU?@oy1s`JSwyyaxNH*q_QE>yCrgHx&0F=-Y4- z;63z*f$gbExNt6U#xUVc>MC1-m=fT;WD}DDAs33q+wS0eZR;A?CX(2GHz~|2wl(>{ z_E?}T&#(F}f@KA4J@yh4p9ecweft_S$rNU7s_CZ05{Z^CViBfOOv#jfX1_AcL<8s3 zk{*?6`m#X}VkO!|U`r)pevbg#BVJqXJ(Ef5Jp0L4nd(;n_eSORyp6M^7Jf>N;H3v_ zH>PHQL$(o+b;12tDJeb;1n>*cRm(4LLs=BrW^k~Dm6zX(cQ)7avZX4b>ew6swKst* zU*80p1eR1u_O~_H73Lb>YY^BTdcc+k#{=S=@dqDzjQa>|{b$3W0=Dg31q<cv&wxXELAE8REH7XN%8M zzpx@}6szTJ1#GA3qpQ34HDIgyY_BQFA3@-svvT{fV*3%;g21*M?h_lC^k-wLO3*o% zn1yjLvB!JEi+{P$$RbR-FR5nLYhc?7{2iMSf>$MEM0MnAU`s`0j=NH={Y79K?!r=p zwlW_A+cx%bE})hf>Z_oPi!m2xvV1Q1uxHMfHMe!(up|{5R*VU{cfJ_~+Djr@#D}E> z^**rmz^xB#1@tmlB<;=vwhTI{o=OoP@l-Xst|-4$ja}o2_Fs)Fu*YgARfP2}p$YrI zmc3&HNdF9M)gkeD!}ClGz%37z!3?)jP2SrOtCX9-c8ir*(j`4$%W5o@L^nKuO)uVS zQ|&pv001BWNkl(AUTR%`vi1i_*cQNZ?uG)TozVI__UJq|JnNFSFu#QDjfkF;M72GHyKSTIvqG)FW$d6tKNYCV9nIwZ0JH9^)vR7H>%g{PYbKCEgSEN3&uqe_Tc6 z{7QfDx-n73>nKQ>6vlnjzWfS#TZz}Kg$=Ak)cocAQiDJLCqvEu{|aEcq=!XWoR(wP zz?OZEtfR3eL|}WpOnHx)D`0#23&55hqV&T35ZDsj`a`u4@HhhAv8!{y#1#Q&nLUh# ziD}cs+KU&8lFqf~T+X^A;pBnfB?SFvwOmVoA=_(T0b6|RgC~c z04+fv#|>bsfGMkM7r0=8<4ghDm#GO%xk*XtZB9*kqFBe$OG~Qtk*F?^jc^m(Dhe-Q zp(Jq*cdvl$j2%P4NrFOB1n>lZYFHlFV-Khy*F*%mbY0d``VSM>Qjxk5*5&*Nu$_3M zlAagWz?KP54$c8ibpZ6@y0SJ-y;`O zwNb6V_#RY*rcu`+uf3q7 zEe}91_&B17R2x39rKJx6?Jo}nYz5pJx`0~(Tz^#cDC&_2D&Y`{hK`JF;f-Z^RdVhZ z&lN%JH8uKbJ>i|`SrN%u0Zb=J%UcmD7IVZ5>{ziq@Oo4P zD6uHTHb|jkk($R4ko4X~>AR!l5c}mez8we7*M!JL!jlq6cz(`5>3z#1#kd|)vE_X6Ty ziWvQg<^$Wc7Sc&WsK~6~Gw`R~3_9G}HyFoC@nXZ5>cZ<(+{%H;tXE_gKe(@Sm zO;&*I9%i0CK_(H#f-|J3$R4oey}{sz;FgD?f`6|c$m`dW3I@6E4D?zJq2tjHQ!J5~ zEHH+p(zzVrHi%|4EMA+eHuybz1d$AmS>X{t$x7-CMP#{WcGnfH%jE_Y;i4qB| zcq#aXAK2_sAmk94B&lY$c;&KE%j&Br2}cG6;IcBz`7Pj)7C;`b6%ZT=VIv&Cc4!zI z!9i?jAyl-GfcL%GN!7zhVC(IR3Q<^zQiI_u2hSZv;r#xt#&_Q#mvFFXC@)=Qz2hZh z^lN~~q!af|ZTVUOM}mF@aFz10>hUC)C5@Rq+^R2_TUFux7h9?)UjbzwF#onK=Q7tg zG7f$b*iu>hvMqCoz?OsQI?gX%M}J;&-gYD#cMcpJ39wD;qbM4qDA?m@ef=Y_rD&Bx z4d#7#$tsjevdDzsWL2@G{5@G;2y8Q1G-6}QuhLH8GPj6}Gm5@(^;Dhz0;YJMa2|Or zyZk!NH{K5&R_9N5QT*mhq3W*0;!?4_2C+V{{m-{d?EFz+yQ~GoTeqr*Me&)m*mkLK zCD6sh0gvPQ8F*baQZtozGW(xdvE5Qs>zFH+KJ^-EX=^DL^BjNY^ zYYj~SKZ3ujp@5TL6=YARKZJ_hQPoF+TE+oa$kZl$uu$$HERVFwqhTOhD~ z7fVXDb$xnDsOnU1XR8sbynFJTXUh?p1sqDkQpFw~uszzt+T`Ai9299U!^(8n z5-PH9^+TmzAN29q1Rx4UnLW1u0@!kW?vVJ+tIU14Ue~!?`p;-4z~w(a8#@0?MgCP_ z%NvIv*8lh1%A(Bcd@59H+M-ccfE9ews#{S5s}V;8vV36cUmyP%x%Gi9DaZu4A5xL) zUwkglANCAO-qXK-xjTMAgUqFKbq~n#opgj{beykXHZcwY+p^()FjVE1)mwtv_lGVZ zmO!?mN5%KK8VU*6%~=-Snm({q%r4Gl?u!hb7n$Q;rR751i%g=3-pJuG-o^esu)S&f z^H&Fef7avw2yFktz*bR_A7DB70EK85=HnrxznsA35o@7JROb4DuHs%r2jRm?{qL86 zt%yVg{tvbyf0wbYQAmoa!5*;HZ^_RDyUW^r0bsP6VFh<9d>7lnI|6PgAjKY0TH(yc zHDH7GAgA)cAY1_X*$&#G5(%sV#|4y}9uaCH6?x;EPsN^sU96(W zN(E&Jp1o*M;T#F}1=upIq2O>@~jsi@=sN8^$Rd^1SmObl%g4*MOB4KHvp#@2w%5V2^DW``R$JhaY0s z=$7wi4=};)O#n(@yJYvMVRd80?3Vpwf9%b{UfEv;w*LFqTmCzKkM!Vr-nOJUH{ucG zVo~HDkEni6Qv688;`QQxj0iY5k$5=Xb6zDXJSy^f6WI|1IZup;`?PBIV~rGRbMSXl zkr&+nu+{X!*0!iGN(GF&!u{|9McGw9Xk@P-MY|4mG5hSX^hQ$&SbA&;Y(!)Qi>%5T#Xp&^i!px&d@ zUI8pq^^j&_Axx$WWku2f09F|fMIAPiG9}qX!Kk`DApP8;TzsWktbpu4gIc9*EL3HaB2hk&C76BR z-iLtG2c5sPz54tQ0Nd;SQiAPkV9RTHRk5YQ>?H&GYihh7OsndJS|kK~@eLwe(hD~Z zuwaZLZ;WEm8AtP*8^Bgnk=6Hd4dK6)`_BVNTtgM(fZ3gEU|SEls97Vp%oRlG_6P*r zOu}8tpS{{22F2c8rF380XnTy8!na?537oZ z$t+maBT9cEW+RvOc!FAD7&*jgo-11zBLjiYM zCYA!Wmn&O%l~fhm*<=cv?>t~jRp84L(Z=5w&eb)rRaz5@*39Tb5|YRJ*m(C=7%y|C zgOZg%IqISsqAze9O)d7G4UG?Q{Yow?>Mc{lieZXk@^!^Ff$YSDsN}QVr*lEgezpjy zK3JZ14(1NHmEp(3B2;Pg_7Vaff= ziN$B1*D}u~;o!n!7;(SISUPS)0ozB&n+XB6v=t-3z217XWZn8zU`xFds)hR%+q7-r zwe3@p32eC|UJl$_+9WQJ=ahPb_akF85v}up?Yt33F&e{r6m#uJ3j^DY;9cwm?_zWK4yxe?$i;&weDz2v98)xdA~+rmL>3fzYVrZaH%B*7FN9>Kv%zorg%)>mq8`;Vd`naAVgI*7y{Cpwl2MOYvExmg>~#a{|-1|mQvXQNkx_q zWGO@1mLoID^z2HqEcOG89fR( z3g}a+$Q$(MjVMLv>xykyRcxg~!@8AP&;{A@BvX-4`Xm($Pys0)lC<|&!eU&*iWS09 zbP#((cX6OS6yYv<3OCIz4_K=nUjpo9y9X4HS~2fqmBV-_p0@<2;uTB3SPl>DDv+y$ zp<3SiO}kqZkt;5@-D0Q0_c*AQT%k40NC@dv2$?UEzz%y**`cJgSQUif)svcsfI+_^ zCAB4}zZJoI+y~fO%01FM^6dR20eR z<(R?Asfg#yKA%7~9z@n2M26x~{|eZO2$@F}^#WpQ^I4)6PndrUz_kMd2m8ImIP#Qp{wjrKmfoqXGop z=$=RFyYZwXl&Emb{!^+2GfCpB2vb3rqD%bDSF@$6D=kYHtgFgxKt!;X%!t^R%qARc z%ufr=lj0!PCzw}UNroNIX#|NEm;7+Txs>G%O7s95()2Ji(meZU;ADDO`bPaic(}1Q(TanxAy%Kux+~IX#4`O<=j#1126LQf=&ep*buBDbDg?IY1h%5Y zt(YbLGQh1QzPLs(>%{~CPn=YvDdM+<<>z0aY`dU9)2dFYHEm^7>j1&J0<+iE+maO# ziYcpcGE4)s<;h#7DEZGgE?&A0>TlkNk0=2TuQ%^#R_%Sj&7YZ!;5^`6#A_l7#m7h3 znwu5iw_uqf*28|{wYZ6@SpNKeyPqpy%e9SwjZ7Ri>hr;Q-U01cm;hikSJqX&&!o$7 z2Uy<1+r$JGY_?#eu>WRC^$=6x_MA@yR!0?(lzOQ!r}*C>nIQkL}4fSV$x> zZ#pQO2~;93YC#9fS{$_QA-Jt+t_%V%g4?}2 z&+VlES>_F-fc_q^rAoF^MShix<4r7vcgds&+}{VbjAEE3QK=FYc6hg-yr;yYw$Xh3 zy{IB*Tn#1L6pH%I9$Q~L%HI;y`juQ?4cXteY^91!rDPG0Iyn)QXP!=#E%BCQFAu>v zf80^Y9eHrDVtd#Y@u-E^BNUAUs(KtXE$(dcGtO_$Z4O!c{J2Oc$_j8_1KSh4bI0)Oz*YmRwFS)^Q4OWYM=J84 z5d;gcT@8OCB1-?Sw|`u?N$vL^{T_APxAEJzx526>DZRgU`>(8i_}PD_-OqaHw)mQ^ z2X3JnzK=Y80>7F74%ft&?y`O2rOUiU&kI`A!;2YHK0Yr*3SSJ^YYWK7sfzp%OE)UE z1hxdNS9D|#+%EgT)@1)JdvULU?N0EPs@iHjsOkMu!MFmpXA0O7S~IMY<&P_{7bi3D zQvweRiuVNgk^Z$D4vWnEmH=Bmgw=zR4_>L*`c+#N*O(Q*32e{z#d_v=n!uJlQGHUe z-HtpE-(7-Ldhse?OO<2~*qU7e5Le8H0vRd5k?L zD<~J9z=7x6ADmZGRrWw1f$hOI7M?$mDl4h-*~bZ0k-i{_P62g3jCslAKVCxycJEbe z*_*x#w2H_k3{imPT&KtxE7D7mZkcCf2Yd)@6_CB|X;s2bie^h-%RX?SBJZp#A)HGg zM9ZAM32dprN!|h-g!w-n^d%L}54JEl5ywm-f^3Y|KK-DT4uPRR#9GJcMbTBhwiNcF z(lmi>%}~KSsh$+UYFQ!V%n+zLyD>kh02aM1Ju)miJ(XMwoG)#A=1Z?=_LNDl4HF*9N-x6mF^{>8=;C#!m1@LiQzG-zs zb^rmZuNGXihEcGGP~i5)D4Ic(%-}ByGTj7^@4coq5GldlmcVw6lzFdGT8%l#Bz#~? zUu!aT)cNt30-?s=1h!1Raou1m&h93bpFc;%w$TV{Skru9t1M<%x%I2J+z%cr!7M9r zY}cST5S7fylHf?YCZ=2)FI^kex36${#MM#Jae3YSUQb>tAJp>hAuNR`E}0vb#{$=Q zsh)G8C)g&yZ?y0x5f{s?=>#jblhR|(HUQqGOi%OPQ!N+Qdy9xK|q4`_XW%dMyo->~~3u=PQ%*!>)z;9OMAZ^n3X`lYDBV>>=4YsQO3 zn3Ondqn)kcLtslV+laboXtr#5zN?z2$V>sLo5N6)WQrwb^Z?S1j;XkXe~8@=6L9n_ zCT~aew{w20r-eHI{!$}Xg>z2W2`55DCa^7NF_dWC6tdpyvt^HMDH=vW%{6s2tCG7!b zY18xVV_>7I9@Yf5UI4``z9e4xgy(9Xrg#wpU9C^5v-G84f6pujR)8;dQc1ZigNHm zLI)ZJ`8y}42NGlY`@ntT`Il?p^?mXoD4FoiAy8bv+M`iagM(NN3}D9?#=6yyy8Zxl zsiaT@|3ShCH*>fCVY|WvpKS|n80~ri=LehW`nHd8!C=;Vh%>n%I8;C>r#XXN zMl&6pEG;4b^_R%UW1{HTeD*nHex9C+KuWuPes!D3?czOq836J4cx@?=!j8$^{3I%) z39+ytHH(zRiW5OCPKu;QL5{M|)_*-L{v zoJH(gRcDs_qyi~ghES$O!H^C`od_Z~moYu=iW)Vmzx1t@9#paSxdyiclcFr_S?Ca` zFlc9WN|rH*#vWR2Kn6iA&k48J0QZ`5OpjgFTYF7ACQwyLf`Hn8 z0(0$}4(op|{lzzgwEW*8Xi^@zs**^$xL;*g;8^w4lFCeA%OrqG1bBeURMkpeKdIO< zF+obAM}Z`OC6HBM_8fb-kU=f={fjfS8B~+q@qgL-4(>Ltv+4JrCvOrrb%_PQVzG-| zbg+w5v1Pf*vMMVGq7#(>34#PW34-8!XP&!D(J9|a>?F#0WBc3#iUrtmclXXS^UO51 z@Gd%m`CtSz)v15|9N1tS6|bo?x&Am0IS1r=;~aPI?N_otRtS%AlFFem{s^g21BGxB zgH&4elsep?+d+AKZt<=7zB1S8#Oy@=WG1F0`?77tQTHm@ZP`>koit2RJ*g@thiqCY zNG4M`1QP`E-zrAO{7Xk)_K2FQsPfleIX9Ix{ z1KT_3{P+^tSQ1&=7GP9~n5ab!iOS;Vf9R)G5@-UX5932mtqTn0H4w&{6$AE|+bz{r zT+;2BQd|cEon0{V)k#jEcL9w6WxM(~Sg&Ad<}u#-E##sT*nRO9Xl|=G95JqxvdYyx z)Wucq@#i^_oAY)XTR*%&HkuIAD1xiH6+t-^LMF&!fhk1;8gZ%pR8rjn-GvPsZEqM| zUldz`7&i16>RJRfErN;}LoS?DMn+VL@jP?E<9IOe`eSDBiQ|||cKMj;5d58fABU?s zytN{Dqnpyw(R}+8E|@7U8i{jpIp;g_n&H0i3g=%dQ#j|WvS85OLif#2D8ysZw@nE# z*;=xsl>X*zOB4`f`Q3e_lwGoWO*%s}^2d;$m2FET$ON_+MS%+!o>x8?A<@3;URFGu3#}Tg-kGtqQUJ^fVQsNXwZbqZwZOO&!P;P`NZQ110fmriPWE52>($`LKb^+$2!v`t#^2A%dzBrRs7RS{`M&_MC+g{Q_7JIXcEq zW*7?rdN4#$^b^!tsCrFQeF0Q`Ix3n5O7KfMhxYM-t!7C-ID5kX?c)m6x<*?6?pKE` z{}=50{}9Z6%<-{-EkWtW9Df%8by(ql_V04P32e#Kt(&)zGH#*#D29vmlv=oOL3PoS ziXNX=Tr)8R$Y~Q%K$qb0vWtuD9Gb5lA``oZy#7bD0)Ij`@Cmvaha2s4L&;+$`sY(@ zm`a9Bw_^62w*5CiK)dJV>n(`@>e?FUtjh}aWg#Q>{@f;&!>Dd>1bkB9bB7S_OY;G zlAWpFQTesz7ih|G@@yS&D9onif?5S^w}ZEF9oV*+#TpADpRjRRS_S%txH#RH>hNK& zhcgxr$R4v8PJ-4s{^wl0vhZ-cgX8&^s7CoP@t|Y+&@nyIn@q{5%c62yn4$Xt*xpAe zOn|E-#4d1kfh}Lj&QezF4*re{Y`gj`?CN*K6idvfXh7wdPPrMj#qbE0%==gfdr^A! z5WPwcV9%f&b8+TUl>`?3xgK{a;Owqs!wo8{ryX_0DioUB~*@Ut!7gBV}l) zJ$eXKC}Cs|ZV&y_6ZCkoI1gbyi1{q$6m{pAFj>7VbXH!V9uK3T`LU_%VrEj1982cM zDxmASAagNJ5Jh7q4!RU86DNYWQTZ8xC9`Ljqb5$WOA16vzU~>$&Q4_U!Z`Ql!~g&w z07*naRPCXJ>j*vU_Gr`Mlu_6#NF$tD9+~NcEVjx1iuBXzaV9HDS+W{*E>|GUWx@!| z#pyLLikgr8eYd#BEGlHG(e*oHbiMYA! zA4!gBug^uXS{R@9FNDoH9Sm^VJ427sc3unJeUxS&VLh5a(~3&Iq>@aU!kp0*M-643 z(Pmx>VGMgZKi|Ve?@02EDfyLt)+@;`Wx+jl zzbaR-_52&;A~6um@mN+u#y=0(w%W?sojKqqCpbAemivo)uj6#Ql5ew0$Q%9M4r)sa zct1Ub`Ctf{XcEnDf52t6t`-?i?l)VZ2(->QKQAt1kh$ge`TW0R|97PgX6 zhtV)?xks#V-4G@l?!U?u=KSLMU=$63?Y1Y39bX(xBY~P3N8KMq)lcbiR2-JkY+W&} z!p5GSN%4pZBSvoZE(yCBv?Wh1x!?D@``CQ7fThSd=1m(bi5N;hKF7&cMG6z_YFA9{ zK%DqlpeBrWSxG)M27Klm9im?+)UX(}(Oq~0 zu%NfcYmo3-iNMvB=s2yr4^lptj}L)P2iV*cm+jS13~Aj)))PQkQ=pbbGy+>@H&-;T zfLofUeROB!e*viby8-e?2eyHK8JPbK*!~v-TLNXukZFFjq2EN_e+z|}51k*M0vmaW zw^2QjN(7>WZc0j{YK*L89s-A(IL*99^>GLV>n3XYAH@y1>;EJ6d>?=<4WbBORqT&q zYUxzWo?JTk^5=9#cERnAb_<)@9jtrrU~%LIw!fW2KfkPcHG6x&C8N^GG!dCP|G5k^ zzc)BXzg|ZDtEW=!EP4H?TOpJpQS84VYs4s^ec*%=C;};hE}|>~dYTt7!%j&c(P^Nc zdV|tf5L}?w!z0o^OSZOce5Qs-k-t!&i@?jg1qEbpqhoU1#Ey9rUE>Sv8DGfP4ew2n zTCeE$u=Da6&?*A^yrEOx=2VKM%1t2X3~^p0!aYR4x{Aj0N#snLD0#3S@}a~2LjAVt zb#)k7_RvxWO_r4am(pVP!Paf|%_{RK*Z7IAG`nJdEq~76BlAmuE5A!;X+ymae@Drb z)zA2I1%wHj?;~g3LpJ6`emabe@1CMpTvNq~vr}9ius+Qa1pCH>pK}5pj>NGV{Vntw zDb&B6LOMK(a(EOwF~4N=Zfdt>KM9)tQ9$edKKsElPm*Y5UWr^C7i8x5RUa@xF2NpU zu>6|yfO5mb4*HEEYOlV*{FsH}q=ih(hs;z6o9~{Z&&B8IwwRM~(NB4^NSs;CXHTif zY7f!pLinhOZe<>g@21hP{Mhz*upbCuhb&IeBj=PrNr6Pw59k6$#^^|t4uS18=8!BY z!5CRU7J~|N6F5jSL$Ry&feT9xw^Aj2f@G;V_m6<19RcXA@4mzmqnbi$5l(hdnJB4V zRq3;}oP1aTYW(?MacS1>OYbOU!(>M@5e?PH6F6byPrCwK(1CsDsw@5jAIX9l#g=ph z-Us#@*j;^v!lR_*8Rr5+B1h(XQXRm#QL%?W7FM!ngZDu;ng4cQg;};Apcs1K^aKwh z8&QLO#O&X6`!>m_F-w%kk$uB5+`djZ7D}2dY&o+~1+*#|GC{LD1bAPQH@lK$m$6l! zL*Ptr0%ama0M6c0GUcsro}!met9umhN$$LqLc|F!F7|NAdCR#;$z<;ggK`!1XI~?i zNFWsmU|IJf8?&+VlB{h>MJ;hY%bX+|?#OP%zksgg%y2yfj=MNqT|s$f7CGHQSyv0# z+Vm7o*XDtfwkkSs-thfoeyi#m&4a{Hh;Xofj9z;KdzlraClknoEmT4_HYl+b#!@k~ zE?Y~$N%mG9{{UFzp6wMZWD`&wN&piRQ68?V`Jp!}|Pltc;t;SR-hL{MaBX>*Ue8+f6AlizL}F zix(bYiplB{v=fApsimKUVsm}S`i3#@eSpQJg^l?a=)VX)W6=KI$uJ)M@A zv~)-lb~Y0ZN^X5F9!5SCbh2&Tf=>`lKl_C(Gy)cCL0f^@pe1oX1jYom1pn1&61%V7 zqgQFD;sl=wTwAaJ;STl-AM&|(1RS3MTf6AKPhoxT8|21kv1&(<35LWyzu?6FxW|wE zwE3VZil()ofwURGnqeZ#LJo&%AQSLo&D4ciUorhyq?y;VF9G(s@3M`CeaU<_DUwB= zTRl32a`aU%{K*lHvKj2YeUI0MEns`iZ(%(U5@1^qw)Q$>OV(EVjj{a=*#7HS-QO5n zC1d_)v$22A`-v;E<3POWyMc=L26Fy8C?#~Xe|U_uEMqygfHU4;7#qT|rAD98G;Lt3 zf&Rh#ffBVQi|E*I8+P3PD5ghdW$cxF&D+Eb_+S}3$#MaqrEABc02GX zwgaEZV4tn@(NZ!?AZgweP`hK?79hJ9xGA9aAfUkQUT6s0aWC@hseBZ}(b5kzk=Pw(oU6h3?*m2A)m$1;~>DL5};t; zm#Cinn1$V!->U3bnlQ0{kUg{)yTD);o|owKN&+NppXd3%C8l*wLKW9m$kc{etWn zq-hhSmIMNsxQ))sZ-9-8l1#F?&4tSTp=9yWd_`nmr+aE4(W>F_?N3;rh$9~|1ke#= zD}bhemt-Te=;0VO2@@*4rA`l{Fq{Nx++G!BLtsnr$$sQiSjYOKDQv%e0d#A?VI4Sb z0Vi9)$*!mn=L9%ZHS8-Uwz~stY@qYQ z3#fYCaQ50&BsZcE&T*+l|?oSvf=FU=DBC#<6sv!=qRRyZsD616y~O| zqH8FO`mh-cqrvEqh>iL;kFcA1tz5U|UgT^W=M!bTbbvi%e|#Hf8)Y=-UnBQ)2CFd( zSxXa%{bt0xDjsmY(s0Zj{5Ov~K`j|K4t~w=iHunKVif@XRlt^@mXh$07uhIP4goBT z+sJ?W7@Mo_)bWv`0ZoKBXkO?H76K0T&~L0`{rz`Xn2SiV0A2h!C$>Ur&TzZQlyW{P z1%L-Eq_8KwsRsmTkx^59wrW2Ket8|!WQ(yVWVFg(KgM2W371<9V6Usdq^KG8FzD^# zl5>Ign=?KuHi6A5D$gDvmx#!Fmu5+6J=Ee-Pug6)l8~C= zHqE0db_}hj-{5dD1vEB+-92D`UtPc4KPhxM`*&~zbh@}m=TVvc3QI-|OMXgzBf{8T z2elu7t%ba4DFAB*uR!e;unm~V`27NI*@Wo~oXuRDO2{k8uAJ+>c{vE^qA zxczrakloKS|8*DSK`r@4W>|ZMUW)XiSGt zn+c)*kb_QoK{RI#v}OZn&f3^~GL8E5ILaX(ir$;3kNyeUzCU8$|0f)1e-dEJ9$WU$ zUNN=~YfA}o-CzvQeKhsE*z(^&N4w>)wx5fHdDHU;>4DA;{|>93KVZ$ijdb(@Do;Wv z%>_}K_MtqZp*CfpHW@^D%0gi#gzT(^>_byrdDBCG#8KFX?ctl)*GJIs4PnK12l=Fd zbj&NRy=%z;vaGgGSXdhmVl8PQoiMOIX`?o2p)qdCVz}u40%V!#BwY9WUcl^*PEh-W z3`Y47(2^D9=ot3}-2N?KOCU^;ob`W>75`^gvhHFvsiE{ZhTKdHrH2Wu&y1<@FoEJs z9J$#jvU5>nAK6$MA4Yb32(`!q>F;H6fNUxqj|nyv=u{HoPT(GP^?P8>EP<>jQ;jXZlL&LL~AnK1IsLaJcse0+r7>bW4P}))V#CNs?_+JuD|2sk*2cnwfz|0SR>y6bPuYYij=s6LhP4O*-Y}LT z55(^-(+@qgs$W!P$`bS{$t>e_2x>X_HD$B}04u%+ z(x09gk0L!WhSbD3R;QA%0K2ZJMj`E|fOAyR|D^SY}Y{rEtH+6#B<Lw*~6lq$UmJ#`pEJ?KWO-}k~FX|9+Y!La6%ThKJyUunK@La zXHlA-MPX(Z#fP&f%}pae5l1FspqaEKmW+j*rhi2GvB^%dU?6gAC-2oQCJ@k4HQ-8f z$(-|d2@qXo_m=`&&TTr$*Ysgj0wX9>oepdJfIPx$`f%;i?55?FgQjr^B$C_H_P!puYD z#wJiqPN0$)mr;zwu@;VCH90OlP?r2zg zYX#iuChE*o4VkEff)e}F(M@do0@50?k@KAgeoSOUdF1nUt4RojQEW2%-5(nVN9p3l!9^Li~|pb6B; zKyx$#A?d}f2E$ml!zeQ2*I`t}G|LEyOLWR(B5fy79GgLYdJfr{IizRjkeZ#t^2|fL zipB9RmcVj+9GT=4^07(etRxC%0_$cRRewnOX(<7}KKOl(bw6{HgI55ChE5zJm-U+> zQ7#yPE2;9Dreo3LMT+w2sVOYP8J85pn`B(Z`*>1XELI{(a4aVhGT-JyVWh(`tl3eN z>?l@8{U~b26|g01%R%X}n`8SQ5%=>S0c<~_GxWb`|NrM>f?9s|Z@~8B0^7FdGqi>k zu-(#bqvgAc%IIyBNAJo5pAY?-?q)2iELO@|+vW|Ct4dWpsH4o^^WMa!=Tq!>|A>9x zAF-$Xuk_e<9AHZs@`v%cWY}&5?uzs4rUPu-e#P1{&z69gpm8sJ8=Z)9@vTJfVbT8y z(vkaE(mzE$@OzZ?-=U`c0X6?;C{t1$xPjH+4W!J^Pz-*K(&+DTV%^5hgWqFkxsej@) zA-itKYEi0kYgNxFb5b{z({V-XxZKxb?Ojo1UMM;@RU8$mJVQHDJs z&lQ_Q28Sj-luxF^Lr6vM<8AOWWD~cs8M`mXv*rCvfNd*GDdt`2qh;)lWWO3iXa|M_ z3=-5a2XsB82LG+Vtpd0Nx!jLG2evM_r8Jog?t1tZ)*~N)?S}n1T0AyEjvK;i*NmIu zVB1WZs4;^yVjvT>P@ag2BXl`DEMTz^9YsDiDnOH&wOQi<3jX`p4EwPgF|Zk6bj&a| zO|L9S>w#a+){?npPi8ALibg~YGKyqw*xSa1!x|;1ksxwGA94nzt{wqu1VruN5Dp?E zs6O~#G<}~)QGx7q#=eJibQr5q50>l^q(fd|Df#yWb3_)CH8OF+U=AY{x+_xJQ$quM zngH9~QPmS#iFi=8MpO?e`$w%2kY(m}Gzj!*EM<_vQUHv-dw&jY8=(NoVM8Qrbe?2Z z;A+@LIugNJG>T=*L^c+}D%ss&0M)2sh>Cs>b`xRMYbu6Ht`U<0iUMj)1rB*U2;eBE zRg5OVhgvvuo6C-~d5s2cbbd8;teA#K{pixldq~v|pb@gL5emzwheD`^Lt?~}HNBt< z?s|~tYzSM{1GJeJ?fpV>bvKP6Y?;H-%PR(2*UY07!>zX6?L}t3?Uv4=81F5=l6ezM z@E8hs)m5J-`^CtFsNwc@2IO}LtOyQNkMRcsDi_$gpw|8O-vqY8@I8?HYvy3PS=fvy zs#sp+L%PVyQy~+}VGGM)6APA(_offaT;L|cB28q!_p%Yds-Yu8a};L451;>$V^`Bq_m0T4clxJ7)WgJCtt9r40(o;-HEc;)1 zENLRe>wytL+nNu1egnIv4PFn-$6bj=uo#JA(T-u+2#I8t{fg{id3?XfWuxhKp-rjP2 z4Ap2H1erw|bZI&^{JNwRY%^2W)X}s}(9|j$v9J;`CHjTHJZ0HP=_bkR`wUe4 zK`|eqoOL-Akv`Uv@d4O2wXm>t1=A8RM+T9gZ_5{!o?044HMOV$g8@tKpJdc|59$Ph zIMfUrcnq|?y0GQ!W99i?)lFo)LFDwXM9M4$!dMTE$yg1JW5G;d*&IW`m_WmmK;y2B z15XtD{wTJr2lomLLiBv&lbrnV{=w$d}Kwj9FB?0Gtc9?6%@&MGw798 zBi>_qU9*o{$&l&p{2|WBbtUHacutB|1cgu-xljmMsx5*x2zCYdYBuV@1j@mL?GtPUKE;;#DYip5!K_+F&@dyDOcEEl1Rw4olU)vZg{|UZV#9ub zro}jy`{I;b^8E?rz$a*i?_eW*Pev=sD3b?hhK595ET&8Z4?#wmDC3@W0pnzIK1VTp zQyh)S7PBxwDRC|IK;m{X(Gg^#9+X(2x4d9~)jAi$VNK*s%wc7IG5bvwU{U~A+=j&r zO7+;fF3ODY;n&i4>qwNz;ws6riVTumTqhs56H>BgvQIoFbf;diG+}LXv7q#~5n!sG zLv`$Uytu8D%{5IQwrw39%a1L?E3#Y{loBXhmlprhuW2+?4GasrRWLm$1U2c;qBO7) zW&af=lRi|*TKb34^xc)-?~Zl{2l`zcnD@~MK0wX9EB)7LYe)bsd*xEbDAM{6GX5bH z^&wQ4QyNr~Udmy4ekxHfP7ED=pN12!7ahMx<_r7X2{veQ#lf%FqUyXALmEo9E~YbF z&=Opb{orEXWrfJ*av{s(NH(ex3!)l}fUze0n_NJbYnKbkqN$;vdr&pJC~G5F_uRiS zfD%)xD`#Q$*s4L`Mdp)0QL(lP*ph*hUR9?rSJ+yE=h!1XlCp@m)M9Hr927Gf_FHa- zBiIT>&<@406^@}9j$kt$N6n_ui&qxp1ks!N9hv7;AP}swx19Zq4O219{9O*k04iX1 z#XLJM$8K+I+wT!(OtIV_fRc*QPzE!9DaTZDJ^@}d0TRb(N{dwI485{z-(ADYBXY^QO?hR**|C=#q&-B zsV282pbKNSVOk>XUk@D+EYX+*}F;qfH@mo07ES!35bP2*Vwg9R?RljruRsU@$CP1(j zOd?~(k@AO8@I{dGgs|+3V$mN%DlmqUIf+f*ICe&3=-e~0Gh$)O2%%v|QMMB(Sz}l? zCQ;GH#HfnB!RuB6*z_879U3FKqr;swI<&biPsyfWNE3G-}oAq$yM1es6_?03!u zSxkx|$9t#tT>qQTlZMl&=up#^H|b3M{Qwu34}S)rYR$% z8`2lcYl5!KJpTM!f?64xVr+Sg34Du;+X+Nb&?CtE!!mN34R>VyHZpn;t3JQ<;bwdq zvR^dX>C?#Ik= zC4eQEZEJUB5GYWJtiJC!C5P@xE^f)VjSQKeaT5#10~Dtt$d3n*PY$D$xQ|+F1htqC z)tD|l!fRt1*2YJXjot<2vINMd_8l-E_b_+|bzNn=w(VOWYbx^Lz)kh}+AVaw{M|d) z9=?H&_cpdXUx2y7UHgu()eYYtP&2+j$-akNcvyO-C@)P%e9Gt{YRKza%#w`KOw>d^ z>K8_&6!A*GA^QTG@gdZ#n`k)uNh2*r12z1&uobwAwyp*j^BnA*6YoUX-vSWIeIOz2>o5Y186B0;31K`h2CyiW%4K4~~V*N}@4^m>FD zBzvn|jumTrWg>NDIHgRZ80|xoDE?e!+^W1@_Vkk3-w50hKrT|`kO$egfwi$PmJ+tu z`%A1v$ct3SgO#vHdeqWUUGibM@N2~_0b87tEyIIN+bf`f&bJ$(U(47kuwSw@kst~? z8?}Y~O2;EuOGIUXC2UN{l;0shY=kv5ZJ#jTR5-M>djc4$5exCBn|}iC{e* zM>!TpC7wVfKBiuiNdZr5rdQZ>GT0UE4(h&JBHtx|CZkyho5D&<{%6Pl*-e54jx^0y zgbh=DjMv#eE*d$=8j>9(Yo`9r77($@h2hl*%L0*$Wr9dDOT6A`1muES7A>wzpb2p0 zm|b&YR`O#P*eY4AFv}u2cVyNk`+$dK-`HPCx6s8z6pQ0=8A}r}q$Z=t&yGv}BjvKi z$Fo?S978G@MR6jALX_^eewFKMsLW^fq}R0}aZo2iNqIPx8#R8POt+~3c+nmffJ^x! z*~~p%$DtKMoq*2p<9*V?n+aPYiB=*(q(T-_R#4cKv=tFaAZ39B6)U=qN<1b-jg}oi zb@U!~={P-dU%tn=OW;STq#9vasPpf6{0ZiG%+n!TOlk-a-OSFPgECVAwZ95(6)P+Z zr4tFHt`$F;W&lk?xf3(@Qvf2PR7^(3M8N&wcBCSd8z+!T#$~J}$B+q+DYKer6oq(1 zWUX6)fH*BPT7+|NA!cJf7RF*!fh?L5@t9HK%6(gogz+|E<8?A9(LMyXWO!MmB7?Y1 zM%1>k5;Q@{<#LkecoHk&n1B^BaXijEMoZz4uv>iPziI44FhB>|a=^g4=9B08hRt5X zU)N*Hh!>hJkrCwQlU-f3LRhdvSmd!vj?3{P_)M80aq+E%W03w%zaeaO+X$lNfJ!Px zR%}D&Iwhza^N|RaV{v5IN1GT&AvT6WIEFmIb0ms|a0Cl7Z=&LAOh;ofkhxeA@9hxY z#bTI`#)Jh;+cAkKqHFGABq7^K&_@*ufpj)#qG{OZ>R}xC!`RkouoRb;iR}1Hkx8UuGgzB=gzUr<>u}k^H6xQR9 zP>#)^5}QONF(uzi#iy`Br{Rf*SWQmKoTK7F8IP&?E5)?1g={o})p!hxu{fBMyWs2( z*QOWZY`umQM(Tc3%%n-yiTX$8S>Pk0(W@!4&0uE#EC{`0og4 zXvGZF5;jg=eh1{%9M|AOW#B+VB^s5`Q0IcCC0(Fi#M#noG@p*))q~%oK(MF%9_`R) zXa)X&O+zu9n*qhpUY8ovAd1e%JH9(I1k`G`gpFaZC_$01VA^c~gxOdS8(+-EpFFm$<{$VscchQY#B57oQ?2dj@ z24jXe_C0rGbUnAR>$$DKt#%VFKOLmMKqK&l7$g1U`3#k>CNRjn2U;b^jLLCZrs)OE zRA{6@bC%<-#GG_~{0fDsFy2w(92thNpw?Yse!0&AXal#gt$!GlUMiU)`|#9YX6{Dl zw)E3BJvW3+-=WKAU=%yg9^!cE6|lFVjE`vWBF0+oxjay=*E9#)E@AuKHz>} zF&7OfrObH`RGMqL~g&SWcCJ22HM*Re9P4TI<+-{T$`FF|5$J*q~dpj%AuXJswB- z`zPqrQJjWRH05DT4P8EIKtngv9>eFifpd;6RYhrAz+&7AW{Ba&tVN3UO@^W|eKk3PV9z=PeGC9MP^5&jvda-53|1?Z%& zl;D+2=2eEP>f=@Yr`K~=m01%_mnhpO<4j4i+pFqIktwBAl4Os_9eLi!8Z$?l;G2uJ z#`GL|%PT;q4jgSchHW%uIRfZ-N`n?&JNrAhC}mOldKRT8<9Kh}M=s()BdKG>xF^Sb-(+en<(gZVjHCVXTMWu2;DB?0S(1m2c@$rr{iA#6@d3^%>nOkY z4)5YN=4rYVA@f1$`iS(Tw;2_sd(qZ)iIyVEEplbUtEB$iuAr+p@k$}Hs*MUex?_Y; z@c9M67Qg)xo0&zR-*pDftQ>dwQ*I;Of@!YQ1)4Q%zWPB7!&lN(X@u~K)ioDhE0rqI@y!F>Fr_~3(w~8W_nEeO$ms925$cY4Ft!fw(nf6*VnqG6%=^*0!-<$!||;D`oBych5p<7|_-N}s44&{`AapMF64@r<~- z7D9C7HIa=+vGn923JX7Bze%%0J_{HEdhPsizRUfErfJ(aF0Z2a)eH*pFbaO3s2IrF ziL3G4G&bM-1k|g_eCUMR;u!GJ;O>IYLORGEqu*)asF+1+W*WjV8O+Q~qyFkgoL9=q;E>xyBP8x4=K=rCdnpa;Xnt5KVB`5S zkyJ0}epC~2kdSV3d>??$HsKhCzG}&MnRhW!iMHwSoOy8u@2W@lw~M z5JLHTJv@OmMpC`}345!{j-e#4U*1>f6wPx<^DoELYP*HY+B)j5Uf^9kic)k;GHmOC zh`0u`$G5)t8fQFzd@j%#m=SPXXV5U}gig^@5k5UQ(Sfra9pDcds1qm}W@<#4to6OqsAdI1l+V8f)=)$*eLP`AtB>@>m?{r*o(?s%L*kUB_Y^=9o{p z&r%wR9d>X~FQUD+h|-feEEqc8`@E`XWthnMH0gt7-+4Zui?WEX`2gd2R2FUBr%7~= zm_Z3ctIVMIZyCbYx+X<@{W)7p6-HjSeq(I^MZofxfYE>E-~7hd{+Bbh1Wa@!CWtAq zTAvJJ`x(K^gHV?2w*q42@Fw}F2C9m;bdtS5(241S85BLQw2 zpGv%s%hrA{hq{41-{+3|F%6?W41!;>lQfnhLqjPi`^f6gzQjRl8Q7&OsIsPKmRwiT z;hc~G#tSkdozb+H7ii^Ik$?U~*c{4uxk7C$KzX7(n*dSPOA|T{O&WEz|0OUiS3$}wDoR`wr zdiOn6CWFYty(ooMObKPi1dL>932Jxz3fS@-DPVh7K<}1F7Aaf2D-15PWw$&xLBPIa zXy}Z^FjyhbrW5Y2TAXunK;X~w$p;Q&X9kR!-v=&tfW0bCGjCCzjUr99HsX^!P=Zy} zGfWp~1*rMCl#WwEP8lfsJ%vp*Mx=+AeZ1^@B&v zf@2(98^<_C56s%+Io`u*eg(~M9?Jr~681@NYE{1_hFfH|e+{tZ0z3cZLv#wOz}~i6 z2*`YQ&KU!end!-VNG__l=sxV=q?|$P{R=ElQRZbKpNL>N9>&)DpCrmc7U;|>>@$Op z*A7PyV6L)6*f0f=QAc~|6cwi{tT%Km$*_mwQG18xa2T~NjA!39(7$u{dVpeQ*dg;98D&1&Frt%jk8Tm=FSv%bsK(4kQ|f zKib7ny@=KCzruGB1Iy!KEGB}OpNXQr{1VOeW%PR;30>ujHBY~ zJ`S_W8%a{5yWsv^oxpd8XW9lZ@q}zch9gm5eC%{>>DRoWsf>RZO5;nqXp4s zEQp~?@8xDd6PYk2k8CTEoNik~-R44)l3`Qilx0S|Jbr?`>?%(8HgO?|x(Ddvn8}yU zJm*|@g0~p~b9R8EYC%BD%2-&GBUvui<2F{`eurE+g}uWzE+yWjkN)5cr-L3&aE=2B z0K32uPQkR#qvI~tb15vn{1!hYqoP#!#lV)mv{n%5fT1Lv(S$Hf`Ps)fOlN={Iz~H% zQa%F*jJi`nFU%tSkQ;oAPPK&k(py>JtKM}Bi-|Z23$IbB7SKJ~#f5uJ&Y6|%=0-d7 ziuXI-_l~!)o1I7V`4eO;6P0inrAQdH$FtaZ{|d(?f^8PZ2+VkYIl~D~a3q<=r#O{7 z)pMLPe&%o&t;IzYpMHgTJ&3#+5w@=4Gtts5kp=%6U`s~5`syb%OIh^j$jxhYpzeF; zea0g(1N;mFK6|9taSU{KaahQq_}z27PsTwel@F_3+s9 zT=M>@3PRmV0p*uJBAb{(!5%~2h$0&sLv!IhwrY7CGi8CFFHvddxZtyak%9#9^1i3C zeZ8|IY!-_sefJ~gqX}Wy=>VO2HiLF?5vThbDk6*5vH(yPCRBDh-;?pI%m8L^J+I}h zojhk+%uhhV{v_d7pJ)#IzPTd)`|&m zC$MGD@&6Cl63AW$wby|y!7W+b`CtGqY(FyJJV9e^9$jX_<4oqIik@=fn&cVi-s4Yj zdfvs!UIXp5I=%w5*MP0cs8xNn zlpOzDhWs0_{bvHn|Frk|=sC7q{!j2R$EN=ae9S?4>&F`0Z`Xm78Mcg6smvtM&#pM2 zmJf545lf)R#|oE-?%?-ikzeEF2Vm=F z*YcGBmy%?fNl_X{R&B{YB94TIsZ|APoi#=80+N8)R!aieuCq&k!&%B=aDIrx@)}m6 z0qOhegmg4LsxOdoMi)d9NGd5b+2gzDde!Jqj_kXGEiy6wJHl+&0(Vd~?nn<>H}wkr zZe3-7GCNT6-v;RS&LvP@B6j(t>NyWZsX*_e*D4|V^$b?ye(7%|a1d$dHDJqaBA``H zsfsC;K0N(_#ND*@d(u<9ZQjMU=Qeh{L)Z@Zas2cN&}ulW2OpYT2s`Ie&L;!dRr=vE zV|E1GGVY^+omXEW6Y`=K_6a*GEUe>_EPys}5Byxl?Qjs#x`QsoEEc$K#RR--+C8MK zQRE*c1<*@IFBvr_(w^ym2e`z(GY)WpW1OQ;5Xh?iNf*7$0vHukj%g~=#khf1=#KOi zQ!f2Wduu6SJ<6uhXM_Y78oeGaF9sM~Lh|al$l%xf@ABMT)SL>qJ*?!gJU5MWECI^P z)~2R0s8)c(L#GG?oLvlL`RhE|Whupw`7=58EDfDvaNNd0W(kz$7L5>6S`eGxe22j{ z^9~85oS7_zC7!nn^ad9||H8?lbqW>TZJ@n@+M_8@wo725a%a`NqI_6^TlRPoKsnB` zG#GMnR#hyGVrVI;b;0lzs3owaL^Y%aK`x6iN^Z;FcU_Swn^W1WR1a)8{n8nI7{yo! z``>>LlcsAOFCHj#ZifqB=3q20e?Y^5kba7#B_i>5*@W2^Ef z$=dRq@E8^uLlyR8A#S2y$>FlIspcmJ;GUeLFW2vd^V+*SlX=0P$zuET1f5(O3sXs~ z#DXGcCRinCZR;Ag{W>~63vIuJ4aS5RhOoDrx{g*r6SErj;Zvf|zQ-ziPj%*EhER=9 z;^5taieGU+70Xj6=v^hL^7ym(skVoinCFUhYt>PB^iX<$bAbSIu_#XJB^>Q{RIyEf zAMxS^`u%}igQuM8ynS-cbN`s>y}ys0TpsgdG~!_#&9y$;e}u6$1Ip0I45MJjL8)pg zF@ZLVF56UBFeg(LP%kglyi{?bkoya-*tPUjZ+w z0MtVdM+E#B;1CzscdjSCH=jk9?GCnIFMx8;j1fWIPNJgO(jQr25$*c1ldqM`n^JEz z{&w6CWv8e01`ZE)C9~MM%5Xa97WX@k49${xSgZab+-dHx?#ltAQ`3`5h1br;U6ZoB@*K+}F zA7_`mU#WEq?^*KLIq&1V*+TZ~XLz4X;7u%orRfPnHVl5G;= zf%i@p?Ud;qruwF=l?2e&H1N5%NiDC#fFqMYx!Kv%`x{NIz}{-*)WfA{wM51m~<=J=SP zmY@AGK`lS~V}V+JE+n<@hiPvHQpypQ07Ib&ai65@VOKRUlUN*|MkhI%7+KNk)*smh#0#ZB+V1 zE~|BbXx1rf9u3HOslnwx*B6&0*amV-mj{h36!vR)Wj{dP9zrWTjEd)Tv_tn%nPS&FjI**Uyv$u&*AV7qZAyiz)$W7~oVE3q9;(4<~~iC67I8<9zKc*2gWdUzFR^ zGKWAgO}5qrwq%U?*>sh4LG1^|_5-jbOO*EC!=gEY%)=zG-B1O9OEL|F)?D}i=Uf+F z3XGG-9nYn(8>~E&k*t-Fiks2{Oc`w1x`k%=);|TM&2PVyNF{=!TG%5- zRc>Fb0;-M_S%9YlKFz<(SiKHv{~Xx5;FiFahG`#qNUzD9g@N=*&o29s3D{EFkbs)Q zx37V1W~g$p$+^g(u9xfA3@>vo{)B;`jQ?N<8{d41OgM;j%Rnlq0|NTU6sqGSf8)H@ z^@XCGM;=51qy9P0noYc&oRB^>_RE&Oexlk4aD+<&wTlA~zzRzw3^LDaPZsbOmkPuQ zBXNF$elCO6C>_4TVBc5AFtDYKN;WasZx$7#K%a#&9uc){cW3T7kDUM-W^?YN z`sJ5mO2Y^cMz%=SEq{lq2st;rU@m2DbJFvCauDdMpYvwX$K}Q*Rwt%^6|faIamtQ^ zaa61X(s~G)_#{qN*n-1C7e7mVE}wNgzPyHA-bwb6fLj3hxky!OPrnq9oDGDq8W|I5 zDX(AtEr--<`WFKDT<}j2O4SPgCv-#q0GHL0M8gmuQ$o7CIIoymf?9r_b4 zeK6?Zh|Dr?4pIa-Liha&7K3rDGJ3^~$$6ytPgOI19k8`yTmYyWku&#rdtuD`lqSFyPt5zxAB%>PHF!2fO_`{$qc z8?gN^XKX9JPf&LvZ&pLYC_YZ8p0|@OE)Vw=N_2<-xre(?cHWod?#{<57cE=BMivW^ zArxW{P|!XFb83|YS%F#sj&$u6(zt<%sO|+A2dS%K0h*4_5qM%!h5D#TzE3Soi)8?eGmWgP&njr|kKz z43XE8ExtC$(z=6v$PHZ$vbJ;$J*}?c;*2t-Q;7U(pjaXT5I)$CFVtb;QDW8qg0d`v z;GLB zNuDcUyVbx#h=x*{$hPUoOc&|8#U9{a&e$@u5?d`5`c5Rvg#@>OpU?V(yBg)ci6psL zq73kO4`|h}G?5UK9J+rNCubC}JtaHE-*w)H`@{F)>-8b~crJa;y^W%UW= zdoTOlqfAczcp%a@0&QM)oL86u(uB!QO?T)aqT~XPj~R!0!GQG9Et31@4IhMwk*G^6S<8rolXBN9Hd~~IT*PvjuFe6Ed!NN1$|Sj6 z`v+(~dMYs_8=57rQYez5ATKy>JCCnA@ACJ~zVYiTmdOhr>N=&pkoIh@#<-q7;k+ z$GnFPQ#BoBX|6*#>Cf2ie~__Vvtj^0I+gg}1Q@tOOHSGGb_d{|4w%R?FjlivB5gNWBl=kC!)# z8!|2w6D&pIgDq??y~0nyfVf33#S=igBXjQToFx}k{Nc620xvg};Fi28pN>}rfTLqM z=jlKaTlO64+8EaDNp=4EEND5bGy7oK8|%zbRZZ^;pgle9;qtHt91eiOCi3`^Wtz@6GaYkG=1_ul3IGE}W3u+PXD?iWZTmAvzuZ(m`ixx+fpKf3J$G zEJk1Uz=GD*zHsB@=A?>>EL5tt16APP_~C23wE~zA_{C^0<5!F=SzA$dTmf4Ja0ztD z<|J8?w3|{_Z1#+uwlgzr;Z5qXSz;!F`HXf6e`+5z>Zz7lq&*ELnGvp0R*)$GnGqkaDYZZ^F(EO0B5W3R~8tl!tYIMh*)$ zvkym52@o)TU}+Voy(1u&V3(sQ87lS{D2HyMLbqfG*zP#MR@|Mf&pT`#F{;v$^XJUv3IbykCVmMV87tH7&VOwuqBvvjiVSjRJZPEfuo z9v($4bRSLouDC=0+8$da*=C<2EB41~RmLYWPuSp6Nszf6vH;IgeOeJ?q|jB;U4B_+k2TS{6ydKG~qF(2X%tJqW* z;F2*^fc68pb=ljWy;9mtKx^Mq0G9yRl{g2OG3vXD9jfc2(yN&X`o!^ccX?g`6tX=8 zD=wJfKJnN)i(<|L%Kn6%A~-rZMEBe0vZ!GWCbK=!<-Lk?mpx^QG2vn1A(q0@Ihh?6 zDIEImm}Wr7z|Jm~6G_y=(Ntn{sbhSfxU7v8HI9p`Wsj{lNIu%061B_pY?H3 zZDKw=j#79GO*4i~594V3*bex_kc))@%D3sBPSE;+v85c@8SH%yDswLOFQ=oUm{0hx z^;n-_K#48^o&y}XUldDolPG26p*t5Nnlqrghoxk~VYk^wtE9+`+o9Z;=0Qq^{Aa*6 zpvmtFunl>|-C8n+>6A)m-HB-&XVP+iQ43~*R?6YIK<9l|fm?1HhrnFv1*cKYA!>7v zC1;X=l2JNh&Lw@zl-*M{$@#9P0sr1D~E)o_u<)4AGe?W@N0!-7R zqZ6>v3PzFj2L-qzS5yTM@kemxCnuwO&2eMgxym~%TP7~pAG?d~**P==VQl&d8X~|E z&2tEDFL24ZE(H>GocJc^eF{lG?B|IXgPj8PCgy_?aa|^h+OP?6&xd=9`+d$&xxa|H)H%}TIGXkhYQCfbwlsG- zJHbWo2z}mXSd8OwWwC-gNQU`Rfl~SR@g;C@2^6+bG^bEv{7-lcd%UO9JnKUBAglWt z|DNwfRSNG|>Mf;c$@k|m*gM45tJipAhtx1?}uJKVLQwBOFpR8fr=|kS?6NYh}2048{ zVvQz8E?X<$l|VM6%%SSRA5jneAVyIQ?S?FyAvz+{K#K0jH&HO};k3G>9DK>0oD+zs zs__1~l8g$QLV2rt3gV0sQ%aE!yGTDDK{gr`gDe78k^6>zz?$~GK57u~nND);IO0$U!p6SXe{pwTpn>!~D{ z`)90MyL~u^TiBoahzxt{Xb9!HyVAsqS-k|-1TtmkF3Qe*8I1e6iu$<)8d-7BaEgGJ z*|<5!kEMhuJ(6l7dxUfM0jMh8YVYuYtk#T6R-E}XBgTn?V69F$=0$~w&Jnq)Q7kY)AVdsSgSb0xN%EuNl< zJky&j%C6y@`S=tk1a)*BJ=(+SyO#oNDJ7*8oCZ){4=jy|ylhtmY&D6wQ4Yp_0j2_M zT^844aK&&+05U(z8!EEsPL81P!A%$)Za zRm|IwNFwI3k}+hw3Jy1LcD^YRO@+|7fmh5Lj|TfJRsSLx)EymFFfW3j~VCr#N3(#fSKyNNlI#Ni@eMfE}hBC^f{cm1irgUsnRRu;$bF=ApS9>e_51E9rw^woL9%U8aiKX})VT-HjK%;%%rV@{8- zlo&zT9z;GEMJ_s|%$ZL1aCEwZBXOW6JFh$|$o8I|6Fe)~w0sW_0B=6UE^_(^3fdqF z&LFxIQ%Xf8vglLQe=MgEW#b26djpRfua^V%U`w%x#k@V#CO+b&t>axXf_EcH)trpt z{0eOU9ALW={03ig{25^NKl_;-?Jtt6dL3x~cmMo3(ERWIeZ~JRI{FP^!E(|23fLYu zvAM70djz<4$2-C_o2Zam0AT$P6$Q)J_OkMZ(R1yvbUC!2y8!LZ0(!sb=p0!$964v2diP`+5Wrqo3_F|m=E2;%A21QSi7KGDN7P`aisYX zCEEnCbmvw2U+zb7?xjTdco)YD((|j>vvQUV{WSM+aDa`&w8!=E%}8 zh!H+Cg%VIpHr6D7Rk^KKOFx+J$$t~zdkJj4tW|!70<@lEGP7CzMxB=%EGVkRkUY!TZq=!}`r$>x}*~Z%V zYh)b_70JU53h=u)J0U8f}EfH1_ek6YB|U#Z@Xr3bhpm^@>nv4D~^p!)CLaL1=xxMwRGt66V$z6 z??N5F&C^5d&=r?=GWJ^YJGVNROh*0?u;n&MR=Y)aWJ)3Z(q6zA8Tk&mbMjumC!X9T zZHk#mwkLxL3RwciQDFp z$nJBL&rszQaEc=r*nUh5U_Ls8d4Cwo_K*PD-wSMMcF6bUVsY%w&4}N@`H8xJDjxu~ zT8e>I2T|Iw1i-UYMaFg&jdw4l)r`-;R6s|nKY)C{j$D7xbu#u?+fRY50=FuU_EWZ2 zy^A$<4c=YtuXFLzlmJn zdlZs>EDYhDghDG_VeF|PL_&k2!E;CKV; z!N160v4QNck{}b{DhV>Bz+`f17`1sVW{2RGF25a`&^Q)G`+HSCk!$2l%p=fDnhIN$v_fQMnlPp$d$2MG0>n(+`4gUC7f9Jn@ z>@MSe1lW?ryV$|mu>wX%uD_)>x#L6cK>A8faLycHx=8P}PKz1N5*_G+1BO+5~v;=_>AMAXG z7*KK2Au}@aOV43uL-NNG{*kIkxl%oD}>@~y@7EUK&eL63ZpQEhqTG+{jWn8hZej(LkRvwhGV^ z)Dql!z?tkW!7TwC*;~q%3E0*h4b^`BtV@)`bi|Pe4N8Z}hLH>76o*qePI@?a1bAH& zJZ_262v3SVV7rC(#}_EaOp!X5w4j?&yMxm+?stA3|K|=@MSz0??n8*74*x~YDfYQ< zb}?m#Q3(^+hEZmZt*9wfA&AG1Mm2P{mR@UqBnJV_1M=;@CakJB}I;9i^frm`sqbC*pF_&hps;)EG|GfIX1rUCJ~8Iwwoc*B$L4HIfuyn>GSSC!9;e z8D3jt%^35;_wwGkaZZZ) zmW`u)UP(OGT#gH9-gz4x2nxo^2{XJI_Tkn>_z2aRf zV%j8Y;`WZZ?G-ySb0{Q-P%tdiG!x7Kt@rn1B^X2_XrmSiqo&#NZyw0y{$Sh+mjt*n zbXx%JvKB=x6h+!f2xF^mZVGVAMtJ8bkDa@%l+epfjJ>lbr?_aZ;k6UNR5XH7OGj&B zRJr(HDA4L&@lu%LzTtVLj=?#O*@kp}j0>s-j&{(Q9>?pjg{emm@qTa+r=5-~Y3Ie@ z{^#94J%G!l%o%uG4(0yA!l1YY2V619%;c;CQVqN1f*ri!3tSf*aRKiV7<002^nA%KcfK$&aK*HxnL0MN6RK4+}e6 z)GZV=8>NtmQb;X}Jb%fWy1$o$pZ+`l&iB-kLzvP{?9DAG{}VpTS>%vDXmw6=KZ{JA zZ5{4|Ozxd5>~623^yURV*d``50}DYD8NZIApAPekPgCoW4;jd5SHoj+y}$9_Ib@xK z1}Xsq%YF@2pCN-0R~-DiH@*l%>zPJ*%dd>>pTpRGabWp{U75cmsO5KmX<*Ap8Ok~{ zzVDF@_hE6!1a?;xlLX~nM+*j4HN{$7 z@30#B7VDvZmn9i;>8}lWpq6>4bR$+7wp+d*vE9#cOIX`=|9vd?-jPYmw5F-vl9N+$ zCEPwf!=5+6bDybv_<0XOxqtFuO7>!N8{>wFlx-ku_)v9xC^IU@zUP9){~ECMz;E8X zhx6qH;IIQ+@G(VsFJYp`6sZZCh!TbK)x2CL9_}-f6d51K0&Gu7 z|7~M)ejIa=5He05N=~mxkIB^5?OOtB+1tv&b4KLAMi1I%k77;Gh6bjLnm!3d(j zj9P zTe|&n63dbh8K=wR=be4B5YhkuAOJ~3K~$GQl_^F{fZg5!&|b$o!@)u{21?3Hj^(oA zUcd5{0T=g^#4Bn2B2!kq&FXI+D^7+t>jW_qvw^)GF@52A$=VOyW(gL^)E`lXez~92 z#9uBOBH!a9$-Lw_P7^4CR5G^fK_9w-fB@U|0G*I^$+A^>w!TYXOCT)63<$8z8A0R{ z5lkjx*r8PScps++l*XQ3fRF3WM0kwP&<@jw~L(7f4DMg}~565s(sHk38 z_Q$%<7+!naJ}y~&;Y^(c4sIjQD>7&_=&3$_jAkq;ZnG)f66rg2J5&*H-^e|{18TY>!3bE-4=MGp~~Y_ zK5J`g28F~R@@|ArEf7S*$6jk)fNlK}*piv`*jf+NdP@_PPk?PqOo(XaC~;?m7A_QcjWwWMIwAVkF8r40NXx} zkI;Dd3tGkyD!ow@%|TUUkh_WkuHNzEK38fGKJ`^Zovf4e`m->xf!X9kEXE%qGx!uc z(knx8!kk|8pN1ay1=pp*Z#iAH%lv%)bqXalW=D+r_6R z&qwdvD7K)+VYl_^My|W6`64d#Aol|_(JYgQjFtGUAB!yFrF(%5-Yj<{tZSQ2UEI* zrJ#k3&qUcr$-Mbj;MN1MR}8HJyB?@jfL4Loy3c?&sy++LeoH>@3NTw=R)$P)`xV&! zDf{4Gp0WK`2DY8R4Pi=|OIq~ZlpfUVunp`m0%ZqhXFHMu=K)*ZggMElY=%9AGQ_2k z#vtoJEsq7tMZ5Y?u4*h%@KBr2zyXWLr*8 zRNoD6+HRz$H|gU8gFrwYqBLJ18@JZRT*Q!k)?Dxws>W?pHAep27FqOvm9f1JY>$gG zz&0~uHw75-F~SG0_kh`ve7Xx9NR}Tf%v(}4INxj_{mall0oeYCu6Z9Vvqzk8XPp4n zCn;rR&)2>bAXwq16j~J_yvn+o{9H=9+&;#=`AMXrIx-eby9iK~Jn|CQT6fX1?p^|0 zg4$1ktzvD-tP+o5UQxR3PTmPD1R9dv-fmzq z;zN-+%PfLK`cMzwa{=ugVUvYXc3EUEdv{g9?R_!T@>pBN*pjvFSBx$5V&xn@$Nu4- zWH544#p9qptxIgP(K4L#Yx#M2RxX3m6y$Uc4OvQLCphazR==a6L(2TU4$ zu-EKNDIN&cm_SLU|9rh6ve;QWA`kb2g(Z=|(UgY!Xv@uQ6fvedY4j@lJn!W{ah=`3 z*62H=7}sJ@cHbwAt;gCD#Ig^T%&KA!dsLpS3w~*)Bg2jAQEcs}z*ZSiDQ1yCtfhSl zYzdaxb4!+zz_uCcg*frj9LpcTtYc$mX+b8Pr$@U|RFTpP0V9!vJ2(d>tHpgtMojkk z(H1tQMv*c@DBSN6$tQLg;1eg@}K{75nvl;*LVAlbkh8(10~0u6Oa zkvJO9egk&4gi+!8@F){Ra?&Utz!i~@>{Fbc9D$CjG?Wp8ms%5Jh9jBAX_G)w7cf|p zm?P!}6WA)#DDG1lM)8<%c#JriZ%^h;2A9BgHp(I+rMKJyC2C-c1ApUcok%1KWt%71 zIz7bx>9LY0(xrEQ3u8l3%*Aza6EEBSs9U`PTxlM~SRVo#HTW|bTV*hH32OCzbj$#% zx(}I<54m_4^8<107qh^@HZJH6?nWR<49bO)QgT;u@EnyDJvvloVTXGt|N0pDp_l;M zxri?J&5OfLoE|aBn%9Psp>C^`V7U%?EcO{aM^r)i<;fu~)>i&0z?Qwn%<0Vr1IR|g zScoTaS|}@nAiAXUbn!X?`1LZVCQ-eh0xBtwrP15*K59QbMLm`PO?4J@Q}uI8POU1G zogS#TI=+vsDrBU$nC!wr3>htgS~9k4UFjE{OAKNwN~# zcNTJZ>lCA{vr}>0J!Lx$ufNqb>`hH$JQBlbERNBkVFA0GBU~Kpi3*3#+?)?k1tf(D z_q60SB!#_*U)v>h*MMM;YyjmB5fGIX?q+T;g} zb6~tOf#X6kzoL{7Los!|@w)To9=vO^pdv*>-b1!`#R)!R$5GK@SPq2$5U}O> zG;Ns}jX2m$@tH*vEY)-EJ|*Qo%5~!AT@9Wogy96X8)&|JgDKm=tY#uZhSqN@5ZXtU z)e?r4?5comFNgMTENLX=0b8=O9$U-h=Zx+D6>RNSVEd)c0G%;ewP#@Z*@;LP zxgG=_d`QbggA-0MKiLJkO_W|d`h&psu0#{j469}Okk|Vp+jI59D>u4?4{WZ509Mf%H}V*=YI+1l&CmcY^EclQWWOSV=? zk?EqWdIpQ3J1B>JC?+kSRZ<0jvt2QZp~#))Ut3UeDRMSEe(J$YV9O)Ai;H#v>3C4U z0sFC6O}hQwL(RG8_V_9=&Awg_)RL|JTfmk*ww&M-;ASEroHUnRp6L{O2iw>?CR?Du zEW3qNY{EGX&lF@j6Q}S4T>n(fFbatz3KqeGhB6shi@^07uytdV)IRrstpc|Mwk?f? z0u~$kkh5K2%LpP)a(Pakonr5ZQfYNf^B$-~(Z_Ors{1l~0FOlCH}`lz`gBu~eiS7? zS4A>WmQMLO<8BCSuQF^^)-8c8ji!{@6#Inz$On8V(gA!Rfx~P{-03AkgzLt_kgJ3C z?#Ep6=6p`mE3#Mwru*9{{qhJ45d(`>01K2_A9SUNdfD@Tekj|*2|4ctJaz(h$y`gU z4rSK6a@{UG97NV3qxk!z$imu&{Gg;g74#!RV4Fqyj!q^r~CELtJVs1o_0(|0VO>-}|7{%v;-0x_%O;E!>kR>L#EmbiUiDEVu z#~j_e*>}H6QzX^T%%ZaNSYErgtCA|s#CVRgPvJ=1zjr2QP#hRW)?~zzr9f*ah~&7*i@)fvUa-yohAsnIdO<*r4@0En6ym#`N<9&4NRB@AX zai8pCt6IjpWE7JT8w-gTHm4^Qt4|wb>0!MPAS>t5<$mWmMP&!if0vP6-^Ag^2~21< z#;h>rA3gy(tE%8cBQ7~Vxnr;93jEDGq++VX_2(RBV;z;j$H@D_sQ98-8U7jAaZ?OD zb&)t+D|Lw+Kex~%MI0ViUaE|WDy?8K@ffMdL*$b`VRt+Qbm?QE9>?4Q7T|eq%e{n! zPZm8m#8IDBIVEpzjK9T%WnjuQB;pEf&Nq%#l$N(4*O%9}Z&xB4xv$7>cd?Khz&sgR zJ&LBCxQzMvoRR&{Ft!A?^N}#dlM$@U(EN)~)%o#Qo119o*#jG}bHmbc>GGYQ&1x9K1q=qtny84;FdjQsx9e=+3ze3CUGcM((M_g%x$%T<9SYodr&fdKtul)>-M);HU1ac+W$mL z|KB40^;lSM`Hy;Rz1I-fZco0(MT_we+X@_#O*q)YDGfl*FL3HjWLQC`oR#aeyNZ)a z8rdgt6vONr{k>A;yI2kOV8zEiQXeXMKrHcVPoCf`pH*x%nLIJla3|s-iDt$ek0G5_ z8E3$t^fjPak*FZL1=qrUEbDg!*iu$5J+-!CYlX4(q`sd4TY^gtFY~r-_o2Z_bvOjf zj;W#vbAOMwaCSyWyDQwS5^%G>iqmsW%{Uo6#Od}5*5^K8k&f23A049)D}j3`2X3Pk z?h`<*zEi~wT>)Fg)UwA``fLqPl1yVMWiG|->`Z;cS$9pz8<`tR({N4@9!X-s*0E%1$UPav+9Lbl)`jamKi|diG0j3a$#f@StZ1|NalsTt z{u_%&tJq3SU}+$NLOgYvvujE+JW%cB&i-U_z9G-J*i;30I#SZq#PjWIQveQ$b z+Xc#bY&?I0qUl4+p_46HKm~3UXjNuVp5#>+LXpHOkmdD#dP_=XuZHTG{T$eOpMM?L zUhlD`ffP-Y$Ow`J%Gx&S&!6MGT2`h*Wb-IhrRj=H?5MSM<8?UulbJ31ulKQC&ZF?l zPXcUfrj3GOU_ZTx^W9aMCQ>JHc)X{8hL=lxa4In?Dt>}sdkgc(#RpKa6R1W9 zQF`zQyNl^-ePTRpq~~08<$X1a&pt5KzkuTbc=xS?7I(!vnUhU>{b@5Xzb#<*0=^F3p zl$7tUi;0^QF3%1@xjMneDfa=*)L4MqS;s+P3Arc3$k~4k*ouK#*hHGwa3Ush&yCq> zHw%?6%riHu=NF^GM$bhs9mYfoORldZKShq)0l(Fhrz z4CXT{CRZ6rQI?!?!q_gQaY)lV9+%Tyob7MoaHlJ=cD#2=mhAZf4n%V9y6^9-fd*Z3 z4~H>hTcYBq{q`KEm9i=X93G0CmF8%|kn&oV{AiadWwlDS?*J%QvHR>b=7JVxEf!uL zpv&kPfDfb0dWiN1AYNGpb9_jc~m0|mPfi3R`)3GqJzy5^1N?y$+&QBz2Y4`8|dk2)3 zAL8W5^|0VGkOeA^<6RsqEnsGo#0)p_udj?kxHlsc`Jb3 zkFSAh-mRwZDVYxCfE;`XP`1M%laWneeHokMzo9g&BS!-y`?fNQ^8J6RzxMAiwgk2` zMDlIEf5C3vO$*>!(ZaSxmnani|2 zSr=#JG+OVUVajG7>mLNRS}*E-j0*CJ!zY~p3-K6MU%mjEbrqq&coQ0~5V%Q%43DLI z3^^eotKF#JbZ!F8kt8y~`y$mX2UNV!-vhQPx3&*0v+vThi6E0vKN4M}-Nt6bhi2$L zDn=i+o{a#h8OeZUjxWwdh(|G=0(^YvNkyC!5>C=~(Owuu{z(GqAi;Y-)+v4U-$f;O z53R88vZt2o!swsB8hYZmr>b zIgi@=-!N_mv7q%MZ3U4^I!OIIgo9cJI9R=Qjd%}n%2w6nk1~Ipld)XKMtThSpORRj zOxQM1HB7Vz2e3E(4j1*Tn7B#2&`DR~MA)OO_8WoBu9|djk>M%gaP%FP6E?E`J6Lh( zh|Cxn7o58CVqs$q#SVJF)&spBQ!BvM1;zge*pk7O&({@WOSvsU?R8))04dNXMm2TA z6h<>QFo5;(QK{BTrY!qZIjP$_q05uf08{o$V99Iy@Bq7wDvIx3VJd86!O&4PEaZYA zl%GDt7SAc>3(N81IYa>B0%hig5|nU)%ZdN?299!Rw10kvoNl9T$5D0S$b=K9zIX+2 z!nnm_Vm%P{5Y5WJ;2+gIga6Y}ajOo(AOn zTnGhFd-_Ovxi6|E$rc7D<^=g1bV%m71c8**cCedTMEmV4WRfwY9RoRA!=fET?w1GH z&do}(kM8x%f|cXQ{yP>Ff@Wi!$Brwih)$gFu_6gwq)2S8DZ5w%j+RzLjhY8t)L-; zAon`3C8*{5(vFSN%U{vW^ZZ;_phk+f?s>p_rvOJ5INYL3cNKf71+-qi#9Y|HlI@5i zd@7MdXY?b^>ka7zRoY{=Z@7cfC%Nv({1XUni!^)p<$J6RK0(2xnN{ox+)hm^6DK~4 z#VC=_lxuSZnKSVBBVca>TiGSqzsrdSsGAAYwKyuy0BSE^V!N1Ag=@Z6hEs^I8%)V;GBp1PZYySbH;xqdX%E`FtUBONN%xbFL$SsGIA) zcZ~DZbsW?yXnc5!g+v5-Tjj;lTq!*`g67oh)ioyfI^OSSl<5xs%)DKG?#2eX3-c&F ze};J{f}9ZLUds9`^ahaY(@-Xu?K9E#S^puhC7`YQ)bPNq0;>wlG6Lv2n7#h<75Md-;4ifN z3T(du+dqS~{nut}zsJ6D5AC}&dAcJm!R(1#9(K@q`4qeJqcXWZZRT;>DB_sQW*%pa zJTB^apq|A^ej0nTuTXy)LB_a+s(A~m7M+g2MWg3`de0?^0-wKU2j z%uBqD3f+Y@GPVDPuKjQ58vhfk+W-1Pz?O_=%IZP==RxdFzQILq4yadv`Z6w-%RqYt zs8)e?3m`*PD*~kyHab~r5COe=tVKe9!h4* zIoN*n63C^2LKZ0Ja8}LZq>+>TbJEV^w4KLAwScqSBDO!i#@a7WPSa_fkFo7bCc-4_yvV{ z7<6`}NmJ1ZilSg98bW*G71|3Quv1lmuZ zh`EnUih>3jc366CGXsMXjnbK&!C|F><3=49jV3Otb)eh;mK#8=4pb{RF63~ST14@| zAm)R9Ff(!4)Ug~2qD508OG7P4cX(I+?YdGcV587Jie&UikSc#kWp^J=*Sl*`!pIEtOOZ&6LeQMC-|bPjNaJJF{R#t%4ipYA`#>d2UI-Q8hvClgu%8nr>V41-Pn(vXwdpD3p8tx}AhTjAMK{2_SjPPN!x4Aoj1xiW!9(m$ zPT?e*!%?vSth9l(b%16kn8aQ>i^I|~(BgJ&04wzG=m5)2oEEFX zLhomCI9XgmEjA>@DT4Ey9u@#UtK0Hfd((3`EfjH5s^Da~iql#XXRQv-J8Qt|2C%k) zy-E=q^D`*?`U@7qQ520R>RLqds9UiI$PEpnHTnU2#Vn5M%Q)lp-|PS@tLj*`)`89r zPAV;2lo~jk&7$(~xx_S;tRd9w5tQ{oRAW!k`S~q2#^!KXuHlRl>a{f-uB@m63b%D- z188-@bD_JGL2F_hOM`=$(={~05!9^+azPXGx`TyBPq8|`B=5c8`ZPK~y`%OM_mzw` zP7BLe8=FGr@l$buUtlrA4x`HB?hpPUU|SBEsQ7rl2qPb|u=ewFoXjoZU@-^qKEB)r zs;fYy1C-i8c?BpnfpihO6LVO9^%kYX08;)SQawIYd^)Oq8X7$sR{BlU`*i7(rJVRW zv#R=N6;pd<4&}KXUx8Z5x&5pcmythS?9U}*`!5YH9h3rJawzBPf3}I%SH|{Vnz8*J z+xjh3ZxQ6(M2Akc=3S&iw=kpK#zNGONv9tZVGh3x{?0LDbM)eU;0Mfy?;>O0LDv7B zNQ&3=A5_dw;2R}H4t)!i8LZ-dL~%=as3vQ2wzA503ZNKL_t(Wwc8jo`!H(x@X_wWdv|=adoX6*!;F3hIqM$M{eMBn zzJqn^2dwIU!J7VWSkwPs0lAFT`Mo{1RsEJ2EES?YWW)VPMf}JmZIKX8+aZ~h&O|Jv zl3`34exzdt3Ihh_wL4fc?t-q$Rr~($mLe0_O3rNP9#+Ev6n(c*4l*+|gjC;M0jYG5 zT_UqcGn#M^(-A+W;sHz~e6pO3gfQpmnAZc6!p&IDHMmUJ7|0Y_x>X*F^Y$f8y zGiD-4GW$f{>&bvu^*f;3Hb*yfS9-X+;h^+=7Gs96n-g&ZlL-@xu@G`$vRz~l9GUR2 zqP!S&uo&fpr(X=HHX{M72X15CcMH3bAXcM(6f?0nGMv0d!YD>e>9a2D zJy?r{M6RuRJg@R=y%- zFv9-(Shqr03Hed%y^lh`hrFo^z)2^|D&jgr(tQ zuvb9de19*hVG9k1%vJy$BZO5eh;skkzX@y!XoUsSG}k@(s?U~%Dgs*;8dxx))Sa%e z%;=nXFogM`AhHz6zgL#+ zKmg5PNPvAcWTBxsXlNGdx+Q7>0q2(5zhbNu@S$Uy5{uI?4P=8pVM*z{T^bp{Y&0xD za3&tZbTW>qWCGIzNz5dZ(hoSFNMbRjj>(d)BWGwJn5>#1iKLo0e3;>O#!RFJqgWV- zVlrxCBIaOvP{j+)CZbpxmkh{P~&*qE>#j7O6g z9~iWiv+)6ZbYhqrc!asw5VDB}ps~*aV@a$imW>FCeiIERA=1$d+0}tz zq~Zhene)j3%nl65zMdW!lzq?rKNXK-E*eKF97EoTqh!Y9^QvYPWs{6DnKm0)D~zj)O`piE=an=0X!lr)rNN) zY+nHNfQ5A@DN#d=j+yuAvah&pGm(Vsqv`kqOoazA9UjD-J%~9ci5ZS?9Mj=A<{bq@ z8AX%r*Ra$dLM5D(qCnb-BhAmU!kDt7n6M%kw__Nyq8Kyd7&T(}U`6mEs0tamfgv%G zTL}-K8H#{T(amrY^8pP@@dOq}hA}n7eLaZ92M>`Md5VRB5lqE~k$wCO3&}@VN{k?% zcz~21MnR9F5{#-y9iM};kwn%RkoBJ&7{=(s$9Oq7i1!bM@o{hnQ;8AG4Lrue@GqDj zeu|0Y1B`{ENXO$y1wv>U4pu@AR;&byP7>p06dz-Q7#nzi@#F(}|7>gobI}pZ%XonK z=mX3}24#P7KTL947>T1>Xjx&o=4o>FdtH&2gCZ%9V0GV3PHQ8J8Z;HYF3T!_GkzW$j^1HtRTYP0~|Jm_C-(fBA zov^En=Aq$JRlk960;|>Tk31~CUEtJfg@?J9F{LJ;h zw^$E+gSFr{=mfu!W5@3hhCFx!?Z8bLE5RG!VC+#R!1sQSb^q1i?=-n;hHjvy-9*{A zCEv^S@YaQSvRpT=Yue#ZzjOVTbrt2~eMdX^omv;|8)0zyxn9rge|5?Ap|KL3gDdtO zkzmrKrC|3X=lEr0tbTCh%wFWp9@%##^OkG}*R5*YmBF~4zZLh>VZlMWDbilbdkHiJ zZ0agcl;B!Eho7b0afiz2t-3}u?0*!QsGBp&NS0jqp7b53oB&czNF?Zg)`%%^VP>Eak z80^8!po8&nP~495Rv*enKqiD`-H_hN6nj_00hD4v0kB=O2Wve);KcExtKUc6x{sWG z2PLBi1%nRG+{YY#WK6#}1JfONN$W#7qDzl&)%K$u2?-Fd_Wy{Q?`#HFR-dW_B+7#R=$Bu>exWeKf)Wtm^@Eef`)C1|(;+7VJmO35gL@DXas6i8&%so3tF6=;mTk0k-v+ff`NVXxhbdButYfAJQQoQo(*18NFYDbE6;gp&l{O zn(DueIsZNNeRcr#Fad+gTqVF&#!*-1Q3SOzOtOm}sO3^+*eaQ_=bEgXlf?yC4+x)~LkbM3xQ(T_fpkoheM=C|^{R$?Q429<$`9tWE*brDyynfI zfM!n6$!_E|8^v%0bgt%cs0~CV(r7CX#IE0ubzh(K0M|61oP%t|;PoKjDXb&K{!7Qa zTsO6zYTdd1+zw`AtDe;$$cDB;eu+S$r2B6%w$fwkN|Bj2%xxk=OIbI8Eg4q6kNux{ zO0UB#jM*5~3~|j)SrG+ZwU9(Rr6Lxlg8`(&4yw#6HC1d2!83tu?fz}ld+sRaTsM&G z_aW`qQHvz8Y{yX49pplm$OPk2gx4{J>14m< zQaCK@%JrpumcR4wWcIjD1bs>ZO&PX|mLhm3GtI$$tB$>irLcWDt{(&T)O!2;kAm9k zOfP$*3Dmf*1bb>*qF4yWBm#)NuJaN8uB5>t4-Q8Kgv~}`NZX8uVSX_UmsI~Ufgr&m zC9(@n0<#e{_*s+~E17W&OHM*wlQW}Y>a(nc1z0g-mP4G2H5(OO0Z+b;-{;Ac)w+DT ze*AZSH$h`nj|hNlnQ?UD!>EQ6$mn6D!!g+&Z@c(;d>@^{J&?<5hy_Ou0-{<}5X8=o95-Br@te!;Hh$Caf!PhKVQSdt8x$DVkg^AW30ZVx!BF1o8D~c@h zfH};BjGQq54*t&L%l$_wGxvKV7)Hz8?*#Q^u?hNlK5##&eWjv~cwFfW&G)N)r}i7) z!}s#oE%%17W+%|F;@~=QU%WR>JU4WF93I5mctQ#u^NB|SN~i2$aZ{d%3}QY$C{pdJ z6GbOvqup;}D?E&q_(Lp22Jy~}Vl2*L$q;6u!kZUweIg3TnH)@4-Qk>w#N>Q+|IVbPF|&gX{CX3=fp6 zb-p3%?5!_BbVmjOv;xw6Uqk!-pjJSzb^|TrCR)Y~G|Zc57`GvkV)LFve9)|g;DSW} z%9aU21q|yqq=-<{ZwQzrxcyzgmcZS(32yWCW5ji925-qA(7Zlq>ZI25rU3GS)r*43 zNqwKh!$>?!@IKnXyD~h+_H$s{3EcySVwieBVC#WeN|4FcZUk>*Q@e*vqYoX^k3#UC zu%ct84~vfmFfnLjVOU3cFoZ(FM47B;EG#nL%z%x|fR183fIOLB^FCJlZeWL?w)cCK zf;W-T?jmLMN`ER{Ru^pz^I;wHQ4@193kw_(QyjI~!5X!rM^+DB%yM*ukio02?}UD5>{5PXOmb3BU0 zfk9z72`0#*UY)xJIZ7C-v0QT5BE-A(3Adr<|d4@#_)GD@GlL7$E zv$)^5odl^IEE2G9_VdB-xejDS!p-;o0Y_xMmsz$Pln)c!Qew;X&RGi3c&sLu-r&D^ z|4v{-c9K$9aTFFOVFhd@6IKfgSfz4+ujA_poE6aLKH|?&x6d^!0F;1eCBR{#6EI~- zX)pmUrNU%XS-4T}RWkakb@M)(kvw5ED67?D0@!MFKPKa6#RL?lVhPN}6PR@ef2O(6 zQZyj|jOWDi;0VfMJY{1cposw$*PSwJxetXDW6SG}v00Q*7h(e_B!@)?J?BJ)vE{i& z11mDNl);jnBY?0SRlzhn{_PqZA0Nq#FcTuMYJV%kEbeb^Gmo1TYAnSR z^Rv})u;m)yxx@2_#SIpf*rU9rhq0F!M$3vK9S8}FK0lDeXd;Hup+Sr$2QiiyhR3$f zMIT{0GK^6>ArWHijpqJZ3)xuhx3H!Ym<}Kvdw}`D$Cyfxt$l#G_y`taBS=Nn$VML` z9eapOd_?lmg~8Sw6bQJDFgm(}hF=%u#vfs98@)knkl_wE$On1feIV;Fsl_p64q?_A z!9w^U(#|8~B9D*{KSVA(jI1++oE;a5d^TVp+Z#fu-$0=!gzP-N4b0h;dtFf?R3t-OpLzfIMU7oM^*k1npFAQo41ivJx<#%5PqyNmG zzXIETabPQeQ`k!~m@bQ{eT$~{oeTv=zXL&VC#V=+0@toj{Z4R3mX{!rz*8}<3fPjl z<@>zPxDIUjy3faTrq%-T`LVtWaqyZ&#{^?S^)2c8u(Oc1-~=eUV=-%WJ< zwLq?EoIvr zDi(>KNhj&sN`lPynm?jy{(zeC<0rk!%3+#jT*_g3T_Tiz6q&cz!_3$4yDLVofCQR6 zwS)K33Eq`Ka7)12aM|Iyp?>DyJYd@iDZ?AZ;3~FO0b7FG+gJ_U#+t4eHnOU<$3s|t z{umnzlc>$TM`h_HmY04*YyLG>XWn9M`kjo<>|3nOyu{*Q5Gj`_ZU=4&Tf5wM1C3}9 z?MHERU;T>p*DtX4{uS0gzLPkZwW)Ee%}iipW)ka@AJKaA9HmEt0`3STDs-&X`i0q? zH}4`d976S30_}H?(H{K?D-+MKI`bOq3-8dLdX2T2*XYi?L3iRebY4A1afIN|hg9f3 z>Ly)e`#%A={2M`Tl^LLBKo~`}bpOVGvwR>>E5!VulzrLmN0qFx|1Q#jd&tCfEdMf$ zmAAj5^ZFUKUcbcNo7dQX_Z~YRKVV~W9II0kXirR__WBj_4<8^+xvu3Gphv)1j)btN z`%oTEV*T|i>`qQ%XKE7N$x&=fyvN4W2h={i!rIIjR>t38ef%BTuYQ%BQA&Qv>=JO2 z?N^SvSB$NfQ_R1se^<<{2Wq{g*PBbwCd@B;dIc;iz^s6<%Ek4*!;>>#U#gy7rBd+D zL;fwtD4VBYG(J2=Yw{UZCSRd5`39R~@31xc0o{-9u{}4A=EN&BCSIWS`Uy%8Y&0Vw zEcf0PP|MzJp7$*3)HPlUy>cvgU0h$+>(Xq`G)nfb&Gw){+`fVg683yzK2qeobK`39SBKVaw02kgK3fYaCSaq#XfR>$9BZD|S(p63%E zvHa#0QV$;@olFQzy`%-OOsTS?R0#EFPp~;PhW6Ar+EbI*_&AB~he>RXO=5F$5}VUg zSf3b^{@Io1zhKeUk+pP`EmPD20&HC{N!hXjmNans`@=J;x(;f|YY@W3sZWezg190WD$X9d!|f9K!H2ofBTp(Bt{reNF- zO+HuU#409M434CqTQTa4(h>0cnIo|WXgdJ|t9}Dqu85Hn!R?hhF##6`8A1-OBbO{_ zc#L6NBZ!Hh#mrK_gGcV_5$%hP}yIIrj)u zg>|JQlrn8@dnAmdcm$=NpJ4UvYiy2=qB}Nfp6Ih#_LU(RP?pdwh zUZ6NQ2+FF-#?|}^*w%uMWU3O}7W9bpx(X-_Mo|q$Pzyv+3q<7SN{DX0img>ZmhxIP zsQ4jJBNNF%Fi%;rFtLFsR{Uyo{86+5s-VE41ozLX-8fyS2`WG}zmP@uD^d5o%BdXjG%Kyj=E)S$dr0ZA83 z2EKLKQcq6o0b7r0C9wVe5+oBWb6;PV9DfdOz2C2c+)sbLfpxzc1if3nZ?NV2HvzYl zKC5;9?%H?UK-YIefbE+97FL1;v#xB{Wl%o>tHKDA753Moqs9=EG8Y?15S?Jzz^9;SI&i-oq;UdO3nU3gn6eSpi#0kqK^TNY?1TDU)?h z?pqHBus`(?r{%ObNT2MruzOm^&RHGDM-5!;w}8Diu*=Z`cI&9Ve}eL3nw;DN&7W2+ zpTzzgym$i4j{~hbKy#9{4$$3D?y+Dlgzno{s1C-(@M&4=7y0ti zkdE5u6P#A(fXxc9+W__&z~KsTyaw#Il{4{f6WFTbyqd=P%sW(GJjM(iXI%*?K?#}L zrtTAYvL{g{$o*S`=3JCO7h`^8oL*sB$*^XPK4cRH>hFHSW_AMDSXM65%&=Tr6^Bc4 z?LDB=HJy1kaZ#&ce{mkGZ=Rz#5Jt-MA!7%SiRdT|CD8rw4p^?JNTBU4cOP{nw^-bS z=|;P~sz$Yl&55^YKYuFkCv$oo+^V=A6$8be75G%3_ETn8F}EIA<-f_ld$MMCDd&~x zeIA#t#MzZP%eA536(z)_YC!Um@1n&0_EQ9_bFXl=mIDr&>Uc2{Y<)$dGO)HHuBX^t z!NpDkN6j=gXWydp^Dq|f|A=O&5A9&D3>sZ=u)yO1Tm{Cx*dxV2i+eFMg2`wbeo#() zov{@u@-<-Vv9(fDC^}#Tr}WydPf;083OiRc2xJ*&q<|+uE+_H|aQ??jf>DB5Z}4{ypn5-h z%j+Qa`p@3Kd+$?h>+c7*9;oH=Z-H|GvBDNBMpwN?F}!5x$o7%7Blscs^jK)cK(ptX zl2kH+iro`nWHBdJ0Us|XmP?Q2)B_+K_wkIb+oJwv}V@F2AFLqhby#AKoE9@(_!LC193pUzKd1 z<_K#`a7$227F9rP&_O+*SV0AD-Pei9900f8r0CBG&z#Q z>QB#bzL-*GU%NXhv4HVGJA1&!9*Z<~GpX0X8^x)mZ0p2WYP1%rzxj{q;9-#wHM5(IbDDv85|AO~|sQgGD=n z%*aD*%<=xR1?7ZHx9Ah)c)xQD>@Z(@U(Tt+YF*;18bAFifIFo-Ski1v-1njJ=qV1y zCY2f4R#)AZ7#GIaB`*04+uBis_rlH^R!1kXm>kAL&=T2sCSXhPqvCh|4}0(7-$<2h z;r{FI-8+F{preCAMP)g30)`AtXJ=c^wq#kBoO2Ee>;2Z=bu6{%W@z_?9^L>Pj;v6s zq^k3swfEXs3~J+YVn={4>O$-E^6w7`wZC1C>8}Rc4*|61I|Xcin|<)7V*3H1mXP=1 zptkwlx*n>o8fDg~vs7KRH38RvF5j!6z#8Jq&|)g21W)z^SPdW6aABiXa@i(anU7y< zl2fbjD*zlU%PiMGEqj9PZs_j<+k|ee*X6QW@^uAl1Lbx#s=&&;REF^~H2Bv*>>J<1 zP-KUSt!Yi5rSmfzzpoW+brMA<6c|4JK8h`&l%d6|4o#kJYFKp8Gar}F8!$G?En(KE zw;K#srYki+W2sB^dh{kt<8!TQEg_^8Y?(W|5iu~VpEujR7A&tExh)_{Bc${GXX@&E zxFsb$s@TUK_OXk7oZUsaqJ7e_}}omgzV?(eeTd1#Eot74pd#%5fisl#lYuZ?Rv>DZJKMe&|rk z=`;>dm%optMyk}XWr?fPJv26#aWFrLk$Y*(##oC~U2O$y-A=5qj;t5LvQMb(ltzeU zGk+6o`Is;}>$Zu}RVispzU$&Q_i<1h!^Qp*P-U5)JuRgnB~@4l@gk^e%5oJf>u@Y( zq)?ne>FbAL6gI&;(WEO-Tc4i;4p{rylqq2;C6-e;(|XjbQz3OIStevxYUrL%42yC* z6W35#quLTY4Pa8W{TbK>%B%s|R@Ie{n+h$>sHoH`)G|-~YLnLpwSh?*-(T@GznZ3N zbEy#42ENCBc?zg*>#>t_h$XC!wG<5}HyUTC^Le)Fu1pl1j13@XhowXo;g*f1ZP=*X z^6zqx>&oM6jxm*fnmb8-UI`a&f-MKN2HFg`Hq}~&7OPsV4#{fhGoi$$H_u=8fs40s^XBt>uj$R_uB+5GKi33Wh9aAg z=+|G@FlqA|Co=e$;nDkBHX* z03ZNKL_t&qbcGsrwp~IAY0`!((8ng8I~~gs&G;-3qpu4Aygl*j*_=%D1uH zmbtFfS?6ABzn-(49Lu+{7VO~;&MQT%5A=y+G$#cJuqJ=lgjbu~SyfyW%()+_lJfmj zS-Ia?%X;2*E*sBJsn2V>C|RzChqpRB2l=xET~0cP!tKOBu-%|hm!%UoJa#Db{rbEy6FGM`m)S#5<|hT(E~tzdgK zRJrw-Fr1jpEdMIt@^7=AoFp)xugI}AP;8b#wOMkEsfJp&q+}97lpskEy$n^RnoBj723G>_LC$SdRcnUz zQoS}I(^P~Br3@W@6W9vS1YpZBWU93WY!zy2Kpj_V0d zae^HjV+W@=#u=*h3)HKu4S0ciP{)=vU+arAlK)9VDV7@9`tdteX=Q* zzS`D7r5bS_!KLZYA&b3e>j3E#J$w;zz^?iREF+ zF-Odl)?R!E>@J~xv58t^AN4wG5FZ2QL7m^~1y0bwi55dtuw|Xk-8C#f{zmdl=^mR) z#Q{R?=Jw@4iu>pSRd5Rr8)wp=;S3j51wfn~=wv}DkBRQ2)KWF7t$|X4t;r|&BoHTEPEp4>&M%J9xHt!n+0JlLs^DcdE3UbO+xc(4K%<<89N*Ie zoSqz@D*K2(l)C)x>h&sWjVc=8#0f!%HADAtFft_WtYgur)M#Cb#R9OkWWPwbHun+1 zJ?IIf^0=i}<(g2~Y}|jX%>e7w&+_@!_nBoh0rcHfTcfHnfA_Kp&@@4o%QxSp`Otd2 z`Iv@RtmVqETmeZ-w`(TBV;7a*G8I(GjkPuRl}1>cu%KGcW6u5(<^}o*t*rp7f2%Uy z%n81Ps6c5p3L~F4pC^hicw za9~|hLh#xq=6WAVUN+0(%%rJVx&^&oV7e%>-Pk-^{6G&m3Nc8Eg3=g-{9W785O#WBg{YRk(G*uw)JORweuO z#~Q}XV@Ckh@Nbg2z|YSBA}VpUU%6gIU9qMWH7=I~sOwLfQ3PGI{1|9=7|W z51@*A+yM5^P(7)k&Qjf|qR#6$A&@}JdcEho2l8HX0c@;dMwN`fu^>nkZmG@PPqbwVHFQN_+@%9)>kqpWmDO5TV(g?RyaQ_6`X87}; zU~B#MkZEA^_v{S_eW?D!Dz^WWywmmYEig=1+ozI~`kL8NV9>PW{6mbT7Ttef!TX26 zA;FHSB;RjxS=lq6mCqB%4Ez!14A?THnJO!fHAA6kTBVJqPX7RNclkNZOI0Af3b_1E zfwLgISb#53U?oiWGUvA$8qM!lgDf@4lJEHyVaIP$Yz;KhxXC;=;7RCYTaIe4e>Y99 zjM)=IEq^H#`Io?!%U%!P!Di?Vcnnt~`h825x+BxDipEvOyh;qL>^msg>Y6O;$6R2C zq0SoeOci%snu4-XY_EbXp>{iR2U}q+=VM^lD76f0rqVXoc>~i{8)nj;D1o@3B6=+F zc!nydrEx;n-0L{@ktcYgCq#0_cBPErR03o1IC7aRm}?_N?TtE1c;(y8*g%H+I{D4# zs;3-GQF%DR#*?R*PNt-m-?$$Gwl)+P>s0}RiwlCRE{p5M)sf|Lz`=VmpE#}oduQmo z|3FF-<>Snk)x22)tfqEu$#2IZK`f|QEV;CSa!dH7iP2UlghR*2s%=T>n!~~8!09$> z7u$lbvLyo5x(-}FA`RO)q5G7I$eD!PE`sY zZ>j3*>fiF3yzh>@cb@N!HOmGuUzfSMTrQW%++^$2H?j^KQnhUW%bOU?^oSGh^QeWDAASI~H#J26h{|;h4H;xM&vg-s(2#RV zmdpKmae{-19Hx4^k)ty9TCOc&Q@87CPso+$SPwfe1|zH!2x-V=nt??FkIj9pImv`! z3D*u_*u4MJ)ayOU{TS6%otBMZl>&_U9tJhCCAI_Ecdh+~neNQbBXFwFHte7Nf)Th~;C{&tmV@IIwrYc_`G5>%y)lm-nf% z5AJ2!U7)eQiRHnUcWN+_ zcegQ+NQxN~>j+c%W`6B;b8HE=lYU&vwCxQJYh)D9mGg5n8hS~(+$8fr`kGFh5xVye zQT*y#yo@I?kj~<1JSCyZRI6pey1_dfCz&re{VM-fxrL3Iw38|)_Bb(62Tsq?pT36? zJA>(P2E|YYmG%r)+EZ9*r*g|Ya}CL74ldiDitPu=ucd1HUlEENlwqMVC}8`0^rA$n z%4gKR-?RU)P)jwIA;UMY8M>t{fLk?LA~b3vU>cJs0&T(9#>WDXf$Ok>tpc(!YBF%E zfU4ooRDq3RE8)yEsuGuCRdp4Fn_z3;&Va2^Zv|{4w@``R5r{M}Nw_3X(+#;*;iZDh zeQv&spsv8GYNmWHfMgm>{hGgx2^C?I?Q$KsPSHD94tn#vypP6JL1`YNNJ+S*qlzn) zSCdm~j)8GG*7a&aGof~?lW=Q%OxVI$7x9ol*%B`xlMtLRJHqE05 zxNI7Vd`t3bsoFMka!n|5Q$6N3QKjTyaHcz{d5@fdt)AlWoWpd5jY}#epD3f~4W0uo z&d}~}VY0Uu)9ExOQW>oGzXCXb;w)~R%7Wh480|!8GtkGLY;%0fP|YeBvb^@}nbcHV z$Yi8633F6I<$}vOzre)>2W0xWlWGIU7Y+IQj0@*~rwz>;I;vve;pdo6`6$LiV7VWo z+6sgP?!c{JOTguO7=layrs>p9v{TCb9C@C=5^KDk=LUf4K57>`qC$$&NF|NX#%Qi! zK*a5n=ryW%+)u|ls671+!%0^hq5EPsaKsSS3)w+u=T#imYqEbBz`9mH!!|A?NSDKd zv-&B{nQzOG!owYm_NLzgwwl|`Qdd-L>B4OCXQ?(CqbNRC2o&45gRLsM^YM-VY88h0 zIWF6nP+h{Z*9jV9&Bi;$v08Gj&Q5S~afXxHg&cqGA5KDWyj?x2NpvmG18E$1v90e2 z^v!s_hAukRCEOBl3AH5}FI`az`8VN}A;;_$d=y3uP#Cz?u-QPl48oAP9n7UQ?#EQ^ zRIOF8CEQZMnLP8sHNY#kH2cy#J0F)o)xpcz8FlsVMAS&MZ33kUvF@3)m6EPq8mL?PB9(3Hw%nlj6>x@k^LI(rmcVFohuIsGECpNd5@;EIdl39^LQ*2Y|EotV%(Y91c~ERP?L4S&Zxw-}zxa#RdQCd`^#+@?~iU`rL4sx!fM z)J|X`^#F%MGr%q<9~+m~BPK@>Zuy(zgdC%cE*dJ_9yh8uub!ZOw2igVL8+%bp6x<^ zCaXEMsAKm+uLry)a2XoAq5T;e;B5UMF1ngDSQm69)c%+wi9C z{_r`r0+(tsBv316O260N%{)`W7NO_&?)jbXqZae?*KGorA$1HUloE2AK&p(}zH~X(P-6qGrp9fv zOpp0|bJ@-Hy@j>#o!480N~X3;XeYb}+h?|s;kaUuWCcb^*XRZQ2!K-em9<}AZ**I| z`ka2|ZO`kvm~uOB>do@_+Gg|?wu8pUG;Cs{ffMs=HHY?wI3^QdFB^@sT&<^D2vl9d zHi4K*Fx6i+E$O4Bd@gI~x-1!_HEoUQl;-F*^NKmKz-7%uZi-Xy{G%R-kq-yrOt&F$ z@0vWVtb_Ch zcys6St3o);F+IT6NFVw<3uB&z$!rQZIY8t51P$gCa)77vzZw-LGvC1835O2)PmMWC zRQ#$n^gp;SWpOT@Y;7$=Lj}I*11#UfH~mY{qv)(@QT zNeD6rCP%Uts$a4*)dk2BfRr#M2R!4TIY;AjiE2LxMN%I*lfN*FP7VQ-=s`xJ%vO${>^H8;pZ z4MJ-T+zR-%gd!VvV-pD=;mUqT07o4`9;!Mhw?eW}Yq=h*70oh9R8@HVn6Jg~V}@7D zAd!cPgD4)f8pm@S;_)Ge?i}RNu;l=QiG&PR2^p8UoNsu{*G)6;lMqq?yQZ>emc!Rf zW4Ll_GsaTPuaq3y0C@SBdAn3@`5poeOI3+tTjL~-8KO4ibZ_0h>Jec*pb+Nf@%-G| z6L5GI^D*4hEpEwTrpDJ!Il07eV}2(1F$SWqE`}2*oI$ApM@KlBnZkHi2Kg-O=SEPD zM`U7#?$N5uHur(T=+(a!SPh)E_5_B@u-YJumO!R0a2IZQ&sBJp5ZpK9n*N&S1xNx1 zWHE^{kFS_TY3{8;PwQh7a>~zYn5(|Wz!ZDJm}y4U)90H&%JulA#_trUlU~1r@8@?i z?^JSl#T}XIquWwf*~S`c&~`=zSXkO=?A{}stgL`g%in{jU4&a+Lu(4tP}0U34wsiO{OG=@ zw7OrItE}oNdviR@zH9BxYwXQ_m@*cun%)Q0y5`Tu~l4YLf z#UjQLW!hdHS8mexY%^L%|NoRIQN%boi7xaVRd6UW|2 zzpD3=XU%ir0;lJ^8VA=BuAelXSX5Yf&0^ZbF&19Dkea-M>3bN++yizFW%7~dC}UH2 z&tu3o!{bfUi5HFbl9Y-wMyk}L7I4n$!dzzti=7#iI#ZHoyC`AE%&B!TYrB|nZ0SX@ z4JS|t+6MtW){+er%y;cM(eOU)gKV$Ku{GP=QcL$ukSfo;$`ns+kT`tjD|bRBtr|*n|%&SZbcDh8G*P zo$7RJW36K5853&hI9zb=VA0VqWur73u$9t2K|S1N9bBq*T6V~oPf_uuNtG(>49~uS zIqNniymm}K$V$GDm{~BbFHl!y79ZzwBV>LT$5mTu?#@?dX-Q>2tGeU|HED^_?Cu{QfUins}|k6Sn%#5@81nVb&Y9~hSXM^ zCfIJVbQ1S%JcN0-9g`^sdn2#Zq^f!Z-r5gwfj!wD%#GFDUzzrA=&(fwKn&SF*~iWg z-(WgsNx0l-mk;c(Oa3s2IK(?qVMvb%sW4G-C%~wB z`ev}DIwuB8SHPCx%T!-YdmU`GR1jfR!d6B3<#LP*@$2fZfnch;mtcFaBQyUDqvp08 zp^C#=RnpUp`hRiE^NZsu=A_Yx2oFblEhjy%NeS zuE(dlJWFE2^3oi$0M|!iIVnHCV{7^ z82WpPBYtpVRwVEUsymJ&k|EmcF4B|;okVJeiI0O0;x zwLFx<43SSFpX|nP_kA2yDiZC&YaFph;Fe^>i!v{R%BK>ctfyH6H7abi3*J!Sl209&2p~F#26>GhI$`h+{>cSk-}=E3*~ULj1u9sU?l`O5k-DZ~!g8JAHfqFsFoD8ZZAMWYVgC6`JaLm4 zO!QzN-UDpxwSX-XE);4dbwX2k))_$|5f^B=OesNYv$IP9NTy4nUDL=Yr7gVFP6EkbVvTs&8)|} z^n9-xLp5`J%{H;NFq<*SGI`MqA8)pQqTo@r)v#rw*fNxvfX$}r@=Y@_Po*SYaICpF0ZG@*dHFmsOMqMj$tm<1+1*2!2t)M zfS<3`aZ#;{0hNpqsA^KBl~rY!ClxP-{hnd?(L>C|S<6qMu1J$CHm@CduO0KgmhlmA zYYEpi;6|l)n~k~3ZYPS&MfNQm_A_jhA=0XXFtO&DGT~W25Nu^L#8J&4Ido8HViX^G2;TU`vA@ z>}&xis3c5z= zWp9*Ss+$a}=5}%4QMIL7%TQ*9n~tTLiY<*(0_{a7SvW}KY02#hP6IjPS>}pihx^-j zOt4KS(AS;C)OX)%D6#;`InL`fnZS{S@qFN}33e9;%6u#X(ZdrQ%*aYF#5>Q)ISp&Ood#!cZ22iitw?fb#?eUwyRu#o2*e*vLaqwMX zz1>(^@)%Dl74RCOp~AuBn7L>wo6520H8i*!YotT<6vGehVLTp}aMi_ZkCqN&dWpDc z2Q!v*=+${MxsGz~L?&doK*G#L73Yf;^rtdn7WIDny{TYdD%(bRZ|RNF+Uyl--}K$8 z1S{13?De2_umCQXFDkm4M=|e~b%v$ZuuL>0Fy$sOp2}ipn1)@v&z$4DaT;XEt1+SM z9PY2+7RcWo!B;L``#Vw}xR~m}tdkH(MtMaHllVRjW!B3a525^?TNGO!V~Oygl6rE4 zf!_NV_q#A3P7C-IqbVtiL!c$V5@gv}Tb7OAY2elXuBx{R!Q*ZmRFn6IhV=Tv304{{ zG8%y9R<8kVuzu!3!`SPCBP=|7j%QW^gMJqVyezP`t>;ONYtBg$GkG2Cpx|1?>lB-~ zV({92e1X114~8Qt%tpJg!V@ebTHOhwx*0uv;2=bB`>>w!;<$mQF5=-FS&n3 z$^9#?-3NwNk^}6j=@iw-U;B5#{TO-gBYcRy;Oh6XFFGINU3-3}=zM}j`xEK;xY_tx zv*~y7`&!$_VA-P*8^e(88xlUuUUP!!n%sn11GehCtgkVT_VPXAtgMQygd*EF1Xf0^ z+sJj%sA)}I8ZWBinka)Exfusi5eHQqNipSBShtP_jW71LB&=(>-NR~o9JL=`3iMHh zH1|mMYyz~w;^eU;;HuLy0q9_05IHZXmzeAZRyTkns+2mAuU8uZ*aj5}$VGIirY4vKDFH3rRTfyx)O&F9h}mTol}z^aplfYmygWBqfm`2g5n8_Y& zga-{j*W=C!LS7#D^Irw2z}c%HJ#}a%E>XRE6g+oDn{}gUFTQ{1gNC9$+-yh1qBZi&hr%mX?7s zKueH)TQl!5pv(8=+yut6y*M1p0YT}V2J>TiS>YxGnk5}@Xrwh^-|evh(d+d5 zK4S_+b&qbuEa5}*uJ!0&uo?XewjzJQPMGbl*a@*r4~?I+RxR^oR~$m^UnMO0I(^0Y z3zpo!;Cj8fDK9xxdATj`-WMH$-rw*c`eN|C>=&Jn@XkFyLzuNc#o}dC&?W3@`xuM% z&s)j<2qpXD7PXs>%^E)3+EbO)l0YrSRzYbY1>LuUErFTfG7`O|V7tAlj=L-?VbsRf z8z1jhyxDQIE}kYFU7Z3O>sW|&VX1?)1~Uq_XX*&cffpH#y>mfLrt(H+)8-}Dea&t zx2UgNr(>?u88*LvjOn;KU((b=+$FibB9_R|N4J3+rlTQAzmo0Za=1VaOt!Z$+S`qZ z1Wj*P+mVJzTEmq}voRB6&hVR>QCk&m72XJ@rWu7+fmUnSnwqwB;5JP_SHM>x*uX7; zkS0A0Wh3G7d^)b4)0;((pKK4ek0(cvPI_i`7FEmL1B_-evcHY``mQ|z)|CD+b#1SL z?d$Hq+X_+T}#waSB+u(A|?}$G^*@vf9?9VS?FxxAo zVn)O@mN|&F7*wPf~a0gq@ zo=M$cDyBu|pq5#STHUM_Y}HSK$4if26KoIb$C73u$FF*h{@(i-ie)hwO=H3BQWe;Z zVV17lElnbt?AM>0c4KI5tclC=Lt|a{u{S>bT1h!M)K$HgUQTTAJdk^gnsLkdaDIk` z7tipM?W5mMV=&nTY%`>p6L7`{nLZq9a%N_(IVs0&Kaf0Qep?+lImh!vHwK*yrmPI+ zqA3)@sg^pm3buu)jbemw%N)%=wqpB-2U`<*9pu^S_87QjeM5z5AY(@SDJ8Z9ktvV^woJne-QuVd9 zWX}ibgHl9hf4obtFsvnvsPcY@)|&VF?vMX@3ACl?O_Z!pue48Ez?G$!SU$=0T1v^} zQ}cP|RBI?R&j$_DHsQ{y;=W!Bm!*~%sw|4FeM6j_*Q`%83V`e4+>qSeQR^ngX=Jos z0?t`#L>&+1PAJvb$VTD0x}163!@KvL^Wi23j#VJO~Z@{vv;JaaTari3A@@1 z=nC8h%B=xh1NH<|?gxf5(_Q(pdAFc|t8i<;wyExF$sc~6WmB-Xqta!ghSNIph1J4_ z+sJTadZx%}#IZL+xH+0)Sl-44#=Eoc4Yo9a(x&dl25b!^UxKY{Zxied;2Q<|XNqks zim{Xn?5u#boJr^my(efGu;s)Hv!eA}XZ~$q5>q`xeQgTm^CXOT{@d?#l0$xb zYRbaAM^Wi`8UzypTsE5wM)|+PGwe;zqd(n^(NqQ_t}7}&onhxZOH8hedU~DyXP|l| zB)RqVt2wv)+bFNs?G32>5&PG`Hc%2pr4%P-1=|(J$5OcraN{jg@PYPJ`;c~LrMv@bdC=uC3(pemgVFinZ#Uo z2)6VwT3E$+_h;`7wr@Ia3Z0sJtAT6aQWC6auINwkgH0r z`MzHU+t{UIOT#WIwrg|^-lyZddi%0i7ZqC*iDTf_fUQm@oB_M*Sb6#*rg_h@;!Ar-AiNnRwxqoYN}&zbM$|qzdLp^jgKO<^_z)I>D=CH%9$#%(~rg1lwZ7 zg*L+NpJ4mJ727|-_Ky`}{A-}s!05Zc*wy!%Wn8D{vP7LTHDg7s{R`Hu|531w{y*3Z z|G(G_|1UPef5Te%W2}ZhMI~|@yjivDu!Bfq(w5NMD9igQU9IKmVVH%QdLb#i` zxjN~=^F++VqO4EcH0(0r$)-Hf&%yQg(F zqfy(#c0PykR2(#YSW9zi*;-6%``Er$urMCI%)o8IiqW8V0K0l(xOZlV108Tx!5 z6N!X4z3wl};QU|%s4E_*Cd!*B%bw_sncqQZ(BklPUp&C+S{Xy1_ac{eFp~&sTzVla zxFG@BB|C(&6$%`2JEg>n0v~}*;f+vNPPAiz4$8?+%qBw^O@y)X>>FUaBF@O%5~?a3 z1aXF+^Y5(#Q4WM;)JWxWdkYKSeu>d^9HZF;UZi8#nVmrOU|Yi4G~iGL6`H}Y>;gZ_ zGDkAw%`j&UfX?<&+bQGa{Wyj)t{gj-*D>m%2_2@Y%FyI>t4(?Xx4NBy0hBS53i6N% ze66ro_HLo#eTs@3n32(t%)5EHkBo9_LXyqo06~x{ITrGo=O-b4to6!p-G+q0RnJ+g zmFB*B9-KBP-=3j%yovKt0b^as_cD(X#Wrv=zN*+7ur=Fj*86R}sI^X0v1O<)9jQ^A z0uI*IshaEFkc=~lCYMPU*&+^MdF%-79Kaspe10B7*(^qqX$&V)n11jOSY6XRzbehN z&QT-v)A^Xu6LlRFQ`6UwMh)L@Y;I$FG>5)e9Aoh$Mjcy9rO+|2wUwo!89nDcKxCqW8u)3hEKQzxPS7xlvBbRQ9RfQW7|x`{JgVp?6l^!PP^U)$&ml7* zDYJn3C(p{Gx|UGmrAoq;4^OZ=mB(twiUK0 z!8V4Kz<`VWYDD4oD&QLB)|@9Yfe^Sd%f1f6nJ-~DFprv#Wic8{V&%y*U~N_Rqugt_ z*VVL-dtWtH(IrJ8C(!X)b-cES!sBnGG+oZ|kn@wcnBwtc{a|&qHWLyOx-7ZQJbnyQ z;jA9pg+u_=)>fsg&WM-6q?N>ML}7Wx_NDv{A(mx*idGz@s5W&<*5?i28n`9c_Ioir zOC+)Q>XkULbJChy!L?^;IWxf=oDy=Y;(VEgDOYi{zKoftkMSarlrZ@pqb@EAMRmKs z+&{$j;QAKCHuL^06LW-Gac@7C5^k^T6vpi?6{rfsVYd)jjr3xNRqnKCA5M%?k?AIdy zi`D2~P>FsdYGBd6je^~Vyd6Tp>cC>;7RupIuH9Pev%dRd8XRe@*z5F!K|0xf$hK_V z#dRCkyJWXv(QcETkC!ZMm1vv5ZnHGdT`6tUtUG&KYS4=69#x=cuC*FYH4UZ=;9dn= zRqSal6@(~XDz>a4tcG4xZ1c`dj61iGOLU?!GX!jwfztzk&WY7yz3H~x*afiU=6ot4 znDvttEa#qLC>F+Kv=fzd3d^5Az|rC~E>1R8uQE4p-oS&#S!xd6RllQo)IPAYiqf+m z@XEI^neZ^#mB2>s70x#of!d+C2Sc2JwNMaoL2syBE^G90osWS14V*5{V7NDdsZ=D$ zlk5b|qZm$HwmPsJ4PhnPA>~_EEv;KBxv65j6u_H*6QvZxkME+8iC{Vv!bm)XrN{q5 zW38Y-(@>rEL_$%S6UV_22M@tORBr55fm*CAVeYdY3!|@ME$A!cOx zHCl~%)YTkRy8gD7$sypkE?-cfq1g}5XZ{9hEXF3E=Q0SpbWW!8_bKY-C2aTgq0hEJXY!mCky0r6m?Qbg z?-Pn_z?Q(#3b1cdX${o2f(al0cY`f+Lltff*c$LMV7nA`1#HWH5)1J(Mr;qqL&L!O zs+50$)S#vLT5#-Hf`yF<-10c6H@dqGtW+@M$3#6Wc?m3}yKs`9#|2-L{CrNVP?0r> zwF;sv4KOwS%pp9QwV)dx0$>mfNo|c{NW~Cp;8tgD_z`fLY7NYP1Qq%u#NI zTchB<8EzGv4cMBnZ(SD}N163Wh-y1$CovlJvGVl~z)~65-BWWVPC$to9;m7OO;dGb z<27Bb)hF0loW|VuU&_QT!M5LWaWI?%C!Azo6YBW8=kgepB#HMtenI2&XN=%j#YKJr z&#joaBF{!snCb8?%lhP_zSgK^NuOvO<%qVWa7-el2)KmaRt1;J?V#h~xouX?0;g~y@RP(rxY%qO!`s^gn5O=H0MpdnxxPu<;`u* z>A-t6JA^qqa{Wd#ln>bE+$gTwSbBr16~kanp67gwj;hUlJr`}mymeP5BNkY9(r(9M zv<=0`T`WWxMtmC;i}|%$*Op+*aJ>Ar8Vv2NKpK%EIX(z;=G1AbPZgow+ege0d*(Ne5GD zABB{UDL;ytM`=`Ee2ePhByhysr2{FoBkOi{pzCwA6ZE^lasj*jPq6sa11vqtpb%#n z94(WyWZe`+8EIXfQ8bIu>>>oNP&nLr} zj7LNTEyS~)*f(7C*f_~*4=G1Hr6%t`E(E1T*T7A_ZWWYV>sK1T%rxr zu{+57w*_R&iMyyI+pv_pE8D%n5;c(yfp~)2vKPj3EP{%!ZorjDCpPUUwq0BLRogUscCD4uuS-mhOib1VKv-|k>Ls{I8k zgc&D-@}pktzWNDR%Ih(rTlV3en65}Zv_L7HNRPz{xwcru?!W*l|N07rY&QzA3|QJE zAJ1ati?47@_tJ6+*x%IO4u69u{2d18{gM9m>g!8rl=E2n@mmxg-jnd-2|FU!%7wU% zLd*g~?iW1=i=OwZ+Ut3afzoQ(D2Ah0q>|?OSn_-=aY^#s}~P6ib#jbg|{v4gKAv2LfOZw*UU)%JC;op)WZ@fa0t7bVNb zQj{$&jjqG976HBs<eA?Cg-KI_Bz$_B81C^fmUe*o;6wx{YTj{_b2D=XM|Ie?k_Utm0@YHdD} z!a^j8*$!7~*OsD5EOhuNcKFa*wFxY?d04YD(ihrXELka(y{weTnT^DdcN3Vg9ONtu zqp<|$zWf5alM{NKV#))fq-aDa=hKOvPduj%_E6tk$HmeTX21Lj6X`Cg_ba{^RvHW4 zkFeD@gyY4c`U0GtszD(44NVe{85YlFa}sYK$XBrQcmVUs&lGAqvnX|Du+SFAVn-as z&Nv8w^AWG5Ir3P*@C|_VpQK{GbzQ=-Ab+S|%8>LzssJ}tJE?t*r zog0|(?qVh#M)5%kmG2&5n~%T5#^Xnr ze&k{_bqkZ$Kd?x3IC=+p>n1*` zYjg-ZV?#I?8NmLlXW0GWYpi|Ni(<-^34_ga1Z&*bhA`Wez~a}Bu=46LO8rkz9DI(2q32i} zdV!^(S6Ci=g|&f~*m(II>yN*~$`=n%>WWLA?t;^Xg4>2Uw-e*BC?o_I zdtwC3!!Kl+<^HEQo}R>hZd88HYyD49{^?8P|CPm5cNEj{b}S}4vFO~wV)PTR%o9zc zcpM5W`Q*1_&5mH5N{EDxMp1CWn0LaGV_bGEY4MFAsL`NA zP#a24JBqG0mP;}@sB{vhvP)=eD&Zli_qt|TsCX_aT^THY^EuXE{e+$ILF`YCVRvW{ zo6nwO>-h_;zkH63p_kYid5N_b-(lfVR=}*}gx(8kWt}`-hD;c7J!4@k#Urw9gys_A z)`?09AE{rA$zsBaPXV@6(!|HH9 zR!4@gGB%3J$e^?pKG*jWm7jh@@w3k{m&#z4VVO=sOj7177Yp$u%Ab9Pl^?#t@{6Ca z{OU1w2A@jX9(;<8;ip&`c#O)c@4<RzT_t{8jE4-!F{a$^cV-j!#J9l#KF`gcBZDVIX#7q znJKJKPhw+o0vm&aD1GxSCevAQXkPGBQe*bI`;^dWsVZzrXGYspDtE!Kn0L=RS-G#1*OH{{zkb8V^G&Up;UcfoU( zaBIN!Qt=D`lKHHKdSttUiST1f1z#TML#N!pJCyPZ!wkC z`n6Mb>N59~j=_aag`-k51;TB`%3#IGV#Ug$!cstOzVs_jm%#r*D31A%FC}vL{>4rQ z#gK(L$3s5Th0>Q_VddFVy%zQN$vMU2zCARIz2On;4h>`d0rtY|yOFuy6`zNS8???GXKh~c1W8+CbwtgDG#*+b5o@?8AHjI^jJwZPH z2$P*DB8Y7Ro(3gl}#J;0tX}osKMsHvy`VTC)pQ7l0f(1K(T1RuSHOE%#+pb0!0)DGm z7Kl*$2C!XnZ%Uoqd5_=I4(4i3CnJ(SIFX2;kaCgF*qF>Zn9O>ZOS&k=Y*GBE))fk*G0b~0u-wg5+`~k|!6A>kUCh3d9JduqfmyJvK^i(#5xl9^`bQ+7PB+79P<}9qaA#7Uh*s|_Qzv^^i zzOxM@ckf^zMD;ZxhDk%|1p1RMhEhIWSy2po9!BFHMm?SIC}v$Or!8?i-u61M5xI@c z&@JpZ?NV=-q4QKwR}+@xtt}Hg5^>BYsDj%V_bdUj#khwRkF)*`HX^pPRog+uaX_OX zDtdf?2Oq+Dt5jxkLo>$td#i2#N^{m864}xQ%6pKp4SlIE?jh1j~0jvDg;E zR3wb?n1fs@iScv>GpVc?j?E-8$anQ({$4kxyONkrI#}SoB9KQ+PV4nTkriwig5C~J zCeRpbF%iL1%ECgNkr-hC=mlR@&64ZMz?*rGc3nW&001BWNklaoBVsjycyy z!FI6h&^4FJlp}w05Y7@+xwMbbjEAW%A5&efOcafGyU6vp80&TTwo&Xz_J-)XnpcbfN;#&K9KIOZD zEn)gUx&2${djr@K_;}3Omc6)u?SkcC!Sm(X$o)I%x|mL;L@mp8b;GpLOjg{l$I@AO zZ7P|?R3eQT*1>f&9F=NqDdLH0%gK@nFD6RxT&5c{T|F3zC-KyB@q=aK+o*-dzKa*J znADBVIjZz6J1K!h@CC4;k!it+cztgPq>tO3+f#+tR)Ecm*TF7wNyq&_l zo5qx%#Y8-dT(Spa>28cA(vmkz7vH?sgHqx%6q1iH>Sxgxb!5Ntx3Sb|VJ+liEt1A! zIE^X02f5fijK#VngqJ0J7|Pq)#$p*!Xvdr+a*;TuA_=Hcn?|uSi9&lE3z0NtJAF*I z`x2Tw(-FJu<@viFmYggqUay3#&bG%y=`BVxqV8_Cd)V%9u^!Q|a87)%oZg5Z$4D$G zIo&jC9ChQO&`GojS?ZKR_ z{g~g2(O56W{T@tMSxkpB$aiM3)Y*+ndj>1*DJ*xU1#AVz3AI6+X@T4ScCh`;!1Pxu zwn@o_Wl-p*g@-M5@e=4@thl5)xwshuwpY}_k#{cd$g6(Ge->`Z2uhL;3qc(ISe^&;}QK8$_;IfhdX za$YAU-FD2y+EGk&pcuO)WrP-@A4xeV=H3d_QjLu&*c!8{%X+t0z?RCbgdjr5%`YJ1}G2K{0$Ai;+8+bJ{THwPVTFe9hg+UF_O-P>FtwRp+1Bc0R>U^i%8; zu%Zn43}M!yI%uO{Yhwr_!@)Rn&hRh};>W@vj72&zWrd{X=Bj65%MN2d9Kvp-69;J@ zn;BQYDev2u@*GUYW5^`{#6Ua0QgUOS%k~Nwv5p`?p%@NJDCv5r4XbT8P;URHnrS)h zDBJB4;+>CnN)Gz0!~9!EAWuTZVH(U!; z_z1WJK&~5Wo3a-W@*I?12j!@R)o2u(RtS4`Cl0N499nm=Z?$8G+nG*DIOkN@!Bi}T zsZ1Bfk_j=G5=cs?QRwc$LQgmH={N}gi+)7Ru2#Z#vC(-O+o8MCxXqjt;J)WNarw}rObWM zyk*);ikmONo!_^d@UY|9*tViF0YN~$elzuY1IOcdNMKx31ZV5>m}cnnKKxiHdT}kz>D-^aXkexYM33lQjff?(5NnkI7_Q&R0(0FmIfb zIdd^zl+Lmr16^^~sA4((<%9xFpP0W($d?p`cvuY3CX-=Iq_i=rV=hi5rUMH>ZQZgR z74?~=p9r>#zV%*UOE6eSWmR2HW-*gWV>*=;*IoYpScjPdWE#D3f?_V75(6ZLKrZ@O ztR%YwRqj0ur2gPwTX18ldWu@h@-&)jYQVPQ#z3f*YnLBGF|MV0sIYMYkiU&7KMmGf zos6e2?j;3G7$!^zVF){Oa|wt=KcyyB5f=-cHs(SWO35_nsyku1$S1q7&~qQtSwdSD zx$Yk19z4WIZ;zB28c(KCNOYm%XRsWOqu3Ue^?hHkUAGcgw&GX}yT~(t(vM>aVLc#CxMq%94{8$n7e)UbX5!s? zT-=y!Q>8tM^}7zX+LKs|bYU@i4|8^})N7>?)P$uB!T#~08f;Yc6iw6@F#6iV=nGj=T8}x#qhS|g5f_t|mJFKl;^MZv>ULoxl*0Na z4i0X{QH$QkZbt^Qw_VvMqjm}-b_x@b45q>v%!ITbwXztovv_&e#c)R)b5=Jh?n6`} z-B`SvMCooE%b|>hAyZ{;0b2sDh9$@Tqw-7N88ZJ5LXqG3JAXB>UIEm%e$D``>92h5 zPq4k7YqALm{&x`gTfP21Q2V~0<+ju9cq{rbHr?A;j<;hW6^7(O_C3bw0&9~UYc8MU zOwd?_1`#xzIY<3mT{_iMQEl0;K0a$);J0lxoHgFBortq8-F1Ke_P*;**WYGS-&;ES zstLZDAJyolTBjireN->RNayfi8~ZDZnE(C@DJwEywP7OGiDEi}ymK4*$j2yIp9okI zE-O)%@d?1zz8x5DF+Z28?TyQ3LXk~h3jG76@ISE>`2;LUv}oPNqIFjcuV{3&6)22! z(q%|ALw9#O@8YoS1`gUkMWy{OShGLEmi>uLzHGJMz(%-3%w`AzRI(=G4kmm@pmfUf zz{Z>;K3BZgh0?t)6jE_ag*#B_Y{!;k;fP=p?nLg>zhN?b6El7U6TXdM-@$MqiIGe< zhP!(3G~(b{#KN%UV%CpIE@3g;iKWgvvaSq`-ik-C;zuwYx{X|@P2g!doy3suU?iQy zNH&Gh?j&;E3FLa>7|XgCOGiP)x)_gQ*^5eUWhLB!)o{Cj_of||ywxRwq(zw2+)ZOn zMPn-FYnq%*=JRfa381&J6TXAZXqy;UEp&7WT+Y~W%p|)op2}h%k;FhIh0)$D2I6rH z#5|0|Tucx!J?5*2uo|;*lucl{?Y5}ftDPN~y>kmw;SdU4Y2>LIW>Vsm%bEGUWD>8s zGI)6}ix<5aJWaTG7VQ+(jS~$kZd`IC3swX(Hi6bbzBi4LxQC%+9K)#;2D3?N{n;4$ zGCulJ9&)`&jAdfT#cfOyOl=EAhk3f50NV!h**YyuM{NP1iLM@uWjWKI!KjBjv12bk{elKnpr?Zl`Z#(cs>DdEaQ%u39~vhSec*#eRTU+%l9 zq=OkoJH$K`d{27T8>U+^pIh)5+UsD+vaoDBSd(L5ixOP)qF|nEG2x(;w6T~_g}IQ3 zO5QPZj~9}hNKm+@dc5q~0>-6a|BDJ8H@UUHPW8MBFa)a{ONJy87>Fm(7mwjpB7y!) z3d23!7`@kn{!|JhJzbc(cOTQ;Js^Paw>TVjF&=d!O5>eX+Eyp!KRnoavJbd#30qAw zB~=+2hRn%6zRr+thImt<=Hqfafs&WPlAlE}#_;?U=KQo6I?Xcw)lW(ut${WHH=8-o zp0s&eCngAwg={ZM4?ai!{v(X0yYVWK!pn39eLeT^G@ZipcmhMo6ehhCW}-B_N?|M6 ztDyWAMfU3Xa`kU+FQXqAnqGF|prI8Ven%|_lZiA64c&8(2ZLjRu<A0KQr|MZ&1Q8b)-D{x)`%-`&N257JLSH3?0+@@lyrc!S+ z&HAraY)u&QZw0NtX1VVRr|-98oH>F-aL{B?<>YN{<=XaXMZRg{6>COHMjPONwrmend z#)PoOdaTt8DSM)hi#(<^F$+1Eoy6j|Utln9W5f%IayuEmfkOBbth%?QoYP9=V=e0x zr3!lkW&1Xk9EPLbhLjq51K9q&e9;XF*)4}}pd7v>C8HS5ycN2E&F~GB>|4^-snmvU zF{_7D?ngPl)z|tI0ngbT+fQ5N&#aUo} z5}3(h|Jje2PsK3N*#_n@Qn8~^&v@iEDqnQtbmS%KGdY~iPT{A2X_>L-=c1RS+#Rok&8tg}Pc1Ci|&Pzp{S4ya^l+jpO zLSuPROnGX>X&^s=`K*UREP{eV6CriVr9l$Ilb5ab%Q8WPesu=cTCps#qfW${dnzv2 zk=vJf&nq@fm%^fEZ+`YKRQrd4sX0_<@;I5B#c^RCr^R_-V-=vQa48Sur*Jm#0xO^Q zO1N$@8bT=&!U}W8To3cUhw>L+;COsY%H@!T-4rW4OEXR{5#(a!~?qVkEW553?P%HqY5>P1v%M6)cLUpBtYGnZz<$0Xu zC$T%$hvgr>#%xboCNHL=5iB?kmb{n@X!kz*3e}+zppZwsw1{eH35|s^8uKM!aRv2a z3AM@+8mlE7O^%}S^=BxhQ&>$UWFK7@Z0T|=hGAX@R^kx>TSh)ir)?~Lbq`xFe*lUz zXq4trD=(nI{k&Y!vO8;=z}g0Cg?XGz1)y^jsJeiNn&~7>@6MWS`&c4iZX8!Z4=U~N+iYv8Dk}!AKkH|6!&dld!h&D~3 z*i3jdbC?-Uu8OaB84*$NeJsRc65jf2LwT=)2`7psdU{a!;X7=PjNo*B1{aG(RLey< zUhJ{425hYX>+8T`5ho)#to-mJX6`+b5ZOG9t6D+z9Un{nE<@@6L)$OyTZR^M``M^| zUja( z2arVIedkuskRUC}lDIa#yOK}20T37rCUp1LRds7k6o5M`De1v4=VFM3HStX=BQWn=<$L zV&hfFkUG$n?|#6>#KcQm4N)XZd20!RFU%y;pMQhp zmlHTFRDk&_zTS1qo_phfpD0;$wgfYwL1^6 z`O9zEotQ!^lasPN-C_;hQUxfoFRlWm3c8sLwkO81{_H8H90$`uY7IEz#ZO-iAw6iI z`T18^fAPZW&nrNQV{i>9s`jYdK(Eq3Cttz(Z)3=gJjCm;i>Y7~1#L)Rp5fJ}p;mcr zxzFW*G9I_fhr18lhhuN%hl6cC;NT*5@nd%uX#MABj>$)`eRt38-vMmv+CNd%Kiv5F zx7iwT8XVud!sn)L=AV1K1?pG7wYpnxdWeNM4Y1DuC3e!m& zliF>hBlN1?keu21;HOw1x z41R`%z*VqZ5OX&d2R}t4_$l)GRpeO9RKJCl$W3gAZiuMaf^`K|_X^6+XDFDTp%l4= zW-^AopML^MS)jWKU>!Kx0D2ohhk3@E$`064@pB7UZeZiZ6Xb{DnA5_b=a62j{1-!5 zoqY;y)>Mu%OQ5i%in=Pi=!AWU!Y36hHN$TD#~`v6kwPG?qi4s_hmhehXNA@fhVVQkaPbMa-)drKnN}RhIpU29$VH zj3Q3Ts_t#n+}oJ9Z;FC2g^HNZS#p9XN;#g}D7phExItv%I!bp&us=QytgHjud!o3B zwpR|Pw~ro`l3P^IWEqMLU~5T$d+D3cF=Nt$XG`7E{BR0Ozx<4Lt)e10{P2C2)H(1< zg0Sq8R1)TIU6=Aot%=vD-@k{nPH!v4kWA!KQLO#?EihjMc6XHGCDk&iba}||c|Ui5 z3+V9g>p-K7&F4?#_efZ;&fHH|lz$H=r_^>j2RPzqCAx%VetIY6FSu{LU39hl2 z;n73M1ttt$1Zuc(|;$*s%QmB6YC3a>efu*LZhuWeBhu^<2+N`4{Hiuo+KkV*c zFPp*Kqc5diGwaT#nWL-o_nrn@Kg62~%QS)6KAS(-dMlyELnCOi|Ev~O zf6Ht9Xct{>ZP~jB`haEgbCcU~6;r zB=wBtoHloGn5&@n{jZpa-NnI92HCOu{0pBBbKJ45>a7;Dp`nS>e`1#=p7uP*P-`T zLG9_*f1Pyo_J7>oNBgj2z>;@#y!wps#@2V=`mLNq?=yUDX9w6?#eQxE`A2s!ML=>{ zbMq!jxBr1==n4q86iD(*`-rF3qM9`=feHF=%wcb7LKrmLu{dq zZFD$EINFhVrQPl>jyl_Dv#bqk)Dn;uDwzNAEAfcUhHr~P^wQWb*j>y4ZRR0wqto6) z_lN=Y%6s0DO18X?S!a-g^sba6TAO%=>5&-fL$1JWHtyhH@)fYRsqP<6><;(6HJ~H( zdOdX89UQd}aU``v32+3;RcuW@!Q34Ovo4Q)5L5+bshg@hD6m>^Z%R%s^KzO0Ubb(F ziZ$O;ifIx)O2{cW0kOP0DBGHdX`)guT}< zQ5qh?i<>tvp@*^d^LIeApvuk2u{cx{6i!-btf9(sMlyNfq=u8_E%Zux%zyta=HgKi z8Op?CIGC9M)>fpnM6bPv{X?k$0n0$r@#OI75&6_j#I0`0X7a6nyxlM+owOb6&4qSs~g1g|BQuAulEuZ3N- za&yRi%}`F3QqxiN$`R4S%G~oB>m=JjImZPjfV?>%A>+&&Z`ctLMq^nuDfi{51rI71 zv-A+70k{p8CSurp(+P<{8$*?4lFm?7di}i8J$x)i5YkK~Mr7Ea5-y>KV4Gn+`+J1) z`XJ)BbFPDfLKfIsSEWIuJjgbBtxfa}wsFMCfA;{ry=@%r@HlxB*{vR%W*`}l1hTT%bjl@c($qT;DFEh(o&u{SPOR9QBOO2QEb4Lv5& z4;5dG%8tspE@-;s=+ZOkFKYN;OV8*|KC8|Rujd0*+Nak&Ko>piqazi!_t91N9~W>4 zNZY$u8=DsKB!)c8^}z3?=k`5Y<`35#R~EUZO&jUaJIYhLx~%Rmf$Wy_x!kWK_I)yF zs+zGa|9!1JtW8c}_Rf7wMH9%mNffPw^4J<`kw6_&mBZ|NZqEZ-su$|hsLI5^q{$1Ex5#(s}5*WJcmBZtyY-(oUqi=uVWh$9z_ zVm6>Wla*i;)u0QuB2pEOA{U`Zlrq1LEB~$_E+*d0k~xG-{4O?UbHEnASJfYG?d{0; z!1LEZ7l*RQ%ZUcTl#7@hU}X!d&nGY*zk{a?S9TM~fBOS=N<~??<$Zg=zPQ`MVdnt* zhb`>4w$UN*vd@!ka&d1D*jU8$mk%ZVhx!j=@dTD$K9{k*-Q7Zmb=>7xcyKFY!@i7N zz3x7`TU^L)13UXzdoh7YcT_yLgxkECLOK#VhFf~DeXy+r9MJx^!PXIl>;DLk?YUsf zuyT5=Pq+U^!QDSRb>P3c^}VZ~Vlnd9+XBB+yMlTB@~js57cOEIDT8wUHdKBjb0klj z3NQTx+w=;{-cpv+`^(cD0N&3ta&GZtQ!(|>aV>@F)13uj;X}Fpbdf{ zvV@z-xQ^a@3EjOlfxQF5o_Ajg+)BQDSD^QZ$BM^*fXhXI%|%R&MnxTWEU9Di%OPNU z5fD+b9(rAM?Qsgr-`bY{{CsZ(xDxBp-a)UDLv|!3s>KvLI-H&W_UVn=19<&$qDkXM zedDnfqo?&i)mm-sq50EKBJ7p6Tv2((<{EIo^XEbOQCp5LbIjG`tS34C9ri`60nCXJ zJq8=Ac$G?s2U)<+^Z@WoOYyF<5fmY(v#lQ{OlV{nZ`#phF`zX&=G6w>Qu}puh$AoW zohblE$6*-!z4V^5CL=x5+fp}{qEP85L%&tMSbAQS5o-BZwe-+Zp_uB)G!b*M8Ag0! z{%h(z{`>uwpHm`aY|k~*0z+4Q*!AI8wYHSvk#JXryuOD~a11-EvH+zLLcAW(J6>F% z;2kXYus;e3sI-BV6-C4r=_}U-5p8Ul( zl{`gYJ5Zk6{WhkD?nrJYy{!xMIo-dm<8q;=XI(@tB`HKVvD4?g_<3 z^_a@X{Z`gf@;o1kfjPJI)@E5>cj$pEGV~<6$m`HOUxc@mE8`y5zvbK!ep{?1+d`*M z#jkb@FYOp!MPu0J0we3yb{Vz9JN8f(HTX-p)XDx>{U-h{-&mh^3;7?v14XmZ>FCNOQ7As^sgj)h|$bkp8m!}MT89?iQ=idQrS;pid zR@FZN?YwQA2ef|PSZP4xW)PR{c?-lYFD*uGgr zN)0FeuyTm*k$TLoos;bkvHep(?F07vwGs-9BNY<-7q`q$COmn=*ax*o=y^UxwKZ;0 z8DH-=1tJ`e$S_MB$4lrkHc>-atkF~3#^Q5g1(|4ZIZC_+Tg%5_`#KfD_*X-~jt929fOtS8O@V@I1Y2(7 z^`Dd1D9WduL}xlD!#xCEMmJv4q+U`tg^ zD(7N*4IP5Ggh8tblXyjCf7F6oOD3~DwEYlQhOcdG;$@_5&3k3)miR%JQTSww%POhzX7uJ<8t6wadxB+}Q$AZOP%B z7`cP26MN@S=(B+K@%g)new}xm=AtoRhyAK2D(S6ybKFsJ8z*2(0m&1v?cu1tjIsC~ z&KiE<{$_LxA#1PP2RNloSE^ev*o8!O%7q_G@;8n#XbuP(u zWT9OENx=4=s1eiSD*3WuzqFBYtS)^PYWu;KxyXduvtYaQ@+H8i124LTbEdr`E^=~l zS&dmdLcU&!j5UP0%`K^E``Sr?WqW+EWk_Z@Z(_voKK;(cRQ-}t4#R)+q) z6?7VNsDC$%Y3nmoo$II?%418f?Hj??P@dTjgIcAgOyy-+n2B6L&GXn6%qz!W%jgA9NhxW4l_EJl{6dpb%72_<} z>Td*F!Yx5}K?`6xLa(g?+o>2~dqKjwcpMbyb57u`O35`3^g3z+xZhKg67i&Nu3~05 zhUvJ4@q~`4N5jDOvO3N_*h(}9(X;Kr+DWcGf1|9lclOY(7BI`2tE`oqh+%j31Z;T@ zd8PUj7Qao0RY@b0djhb z`1|OwJpo%;v~W(qR-o1oS3maJo_K0M1a2=KY#B)*%RgK`qL*HUwexuKzTrflP{MIV z4%$ACRR>sJ$Hd6JKLlGpr1!k`JZSs)`X58DfbAZmVK@eR69NuP^vxZyzv*F@o=Nru z9IJQ=+2`<7*H$qeyL(}yvaM$GiofOhJbi%Rn*=IsH;9+24{b6M{n!y4$9yEfV7!J-WkR#g6;Z- z^aIN0>qYK(pYg{EH4pXXKpd0lb>7~`YtLg#u%$vWz0@=j((+W1KZ5Pw$NPH`czxSv z|L4KBseOvew08yA^WJw+uw@<2T3o|HX%c9!s!oZM2PW3`fh~svnOv{~ex~w$c%`GmM}~BVaO^Wi=oK$ z+Onm`R={?X`KR(%?AZ23ERBD`zYiGikEd?7AO3EgP`a48)|_}g|JCS#N)KThlR&KiSlW| zu%*T3#yfzm0{6B+Ed`qnWy1I}H6%4(`$6{X<39r1rU$kxtwXR)4<|+CSb3Nk0l6B(H2uLmq|3fNL`<~(TS>&(A=n|%b>KL*(Ij*)~S?;qmGhuWTk7hdNC zTlPBiN)m4V46tQBERSDo-sCr`$mSprJ*dC}zoWlb!3V`Km zR4B45u&P3l4OAk^Ys2}RCnDHMXL%uykzj+=tp6OXNw{t2B?-~G!yxW0$>Z2Qq;`!;a> zqrY7`*fJdWGVL;|GUTtmfQ9(TGD4km!< z4Pag;$Uc!{Mt>{)BwzRb@nOGl$nodG?9|UQcJ}8R;Xtj#a^>~I{$m&XpKB+ErL83ndQ0(4bvlX8{|}zQ(k54F%@BYUg=u|Gi*a6VI?JB~&r4E3mcbwfz+Q z+me0_E5YmHjVxLw)_(m}M1}~qCzGm^3ryhAgIY=ZV#pKoDq9=a8+$6A+LEcjw!KvI zM3g${a7|F z);9Ejfbdkzl2BdAE0z01t-{NV=ex9J4TbySfi3TE-v4VG$fi=FG&&QtF#9>dc7^U; zIX-lb%02I=)%n|F%QXfbD{ia3FG`@ZqobH`9E>LtDpZ$X%cH=_iZ{=Z^Cr_G9yj_` zRDRY8*zREQ@nd8tIHTLr3fS`8auO?xT1RqCa9e)=!U;AX3)pf3^lt^*uy||*7tw`ujL_9ne>)!XqX8`(XEXV5>k|g&m9XwZLsa1l~kwOhS@B+-rNeU>oxk zwt0*g&g$h`d$%%=mw#FD@$bNP_yPV1Y|n$TkFS3?(E7(t!1mCO*6`*86v;d4y&Y`H zKGjuG*1bq5vWQ|?4B5AkjmIzNe&mK<$H$;Y};*4ZdH;Z#{nXfF90BuRfhO@ zlQlJ1oIu4Xdi6&Xc4~cZVMpmtI{7shGe38RE5n>5zI&_QOBo+_qW^g<_nBS$o6QGW zzdd~p{PUqawjS8Fma+ZvI|19g_9;rdcDx$3e}>1FWrFCXrHM$DehmcMqIn%z>oWn{ zs&y5M=52UR09VdbXz&%eo#-`bK= zHq3`5*w)>UlsuZ(Zisl40$WYIcl6+uJ+PhE6xi}L!mSUs^wv_Xm$ghMO3Ygx!_K5CnQio_C$GXIm=@Cp4AQHlEcV3E@oW^a}V$SG1!tqXq+?3_mJWb(XA9Q zH=@9HBA!s8x)hE&BG`KQ?Z;jVwOa&#dbN3PN}erqk@pFx3| z09)@6$>HCT{)*QzOIaweopx;$9F}L%rHoIV0#UZgwWg35Rm%%ew!Vnee=yh{?unR= z2>38!fG5toU;Il{-JRZxEpKdE-p0i6gFg&Kev_b7|7$*^eQe(!bOmhN%#mkEy#iVv zYE|lk3Pt{%$JPVei-sbz^bqSQXKf2qNIwO(3|A*Osmn>OspAWaof8L%BQDj`W9yZV zX}2&wIwGE5=I}Ergx=W`sO4jobE}}%LL=yiHG?N$D<0nP`Ju=@*zSpvyc)gzg*>&G z=XsR5(7Lhlr-Lnzf$W6{+o|Xh-h1qMc^;LgTOBV@X@2`G*gDE%OR!}+4`++=+n8&u z`eEMIvZmlI@XEp`2ict#>fby@ULQFPw%rr3m9T6t8i3p5u*L21x>Lu?^SJLSu$?xN z$VXBr1rn$Xvd(YpSpArJwe-|}1lzwyIPyi{^=+U1p9kBsIjDd6^Yei89bdmF*w%x$ zBySI`RUEaqWY*geuaxRRPJ^wN^xspHO?G)_$Bp9|yf>5gJ2UBsyvZgzP2c?2&uhKS zoZam4bM6C&rw?gWm#sdlK-~xS|BO~T{Np3(A5p*c3C3?v#&-V^kFBi6O2{Zns;pse z>_^NxH$brcvpu%`VB6HMp{d_M&A4>}w$>F1iEdgq#Dhs_BgCyf`C0N2rL2UPpTsdz zt`!b=UdXQkTfTv-@u$JIUO5jEqXH!l`&d zh3c~GMNfgPe_Z%+PKzkGwTmNBN>@jcd9hnklX&r`@1(A-0$WGGw!?BcvVx&bJkP(s zO&;gHKM`zMM^>pK8%R6-V7uex*wUk=rj8z>%enV|D^+9p8x`29P-KEFC+rndmmFSx zhk&hD&gs7kY^f5<9Qd}nx4a2#r+b7}M`c4EgDtOHip22XEpKCdw9d)TN_cK$i6D_>sSmT9z_M|z8qVEt?CnaovVdBF6I&GR4DRkuCN?6;0Xk?FC0Z98}!^}v?VN1n&F zA8h?$;p`kw1fX_XsD1M@a>rns0#>(Ad2HE#`e`a^!BZ^;aNfthlexH}AicMXSFs@w zY>SbU04>2*!L8>34Y{6>lmgt39^1>AODW#F+2>D_fb2d*AuNk53)V{v&(#fchurr1cM{eD@(eVr$qR{{?gI zO$kLl$+2abpMF(j3QJuT`*7hXRsYuC4x!cu+mdk;S?d}y_Gc(KS5dcbfF4ZN3nkdD zJ$dXEx!)I0f&Z)ddpKe77gLnC)+^`WgYEcll4Hx7qXgT%l`0Ogr=}BK1zOyWzfF2< zeL&?xh_8x#w7QJ(hj*pU>y#V8tPi$a96F+Git>f~+v#t8u$3A5&IVA+%f9$vTQzSf zudSuPwr(2mYj0L{)*U?oTfz^GuMui#70UzLgb8dei}EtVw*BwrzQ}JRpdYFHH~x(| zUlNgVF4%gZ$h@t2t9Uvv>@IlBWtD`ldkYH!wugu4mCMKuk7CAhFdI#vJvF6rizT;N zL7$2WQ6bta-KENZwZWnf;`?Te-NS7x{QMm~ zf!@>-bDA9kvosNpnow%jA|B;~t&*+bM3%74z2#(<)pccJ#`?hrs@%^E^J{GzHRA+q z>r}`7ZvY+do#W@8EQ*uF|8fo4NR zW^f`S9n*2w9M6y)LF14yqzxQIw*!z z-P(TPsP_lkds1plrD73b72NW;aJirRD5}vsZyXVse{u$FUwUA>Gc&15vhg^c^4O|q zAl|?IU@P}CUwCJ*RSpP0l1D8FC|zq7jg-m=ySsQD9m1?muuZ%bY>x$`K87M+Y8j!6 z!0X#Sd+A_%**UJ4{r&HnOMBk?{wT-x?C(3B&wLg0kwFw3ON4be)uPu*0D&`IFQiaS zI=Pz194O`?@;&VG+SqL~09Xwi`<*uSsW{4i1X-?_`n{QK^!QKm9b5xw4=G<^Q9oAY-0cz6Da=kjIm@IM9b-m&uD-|O{oc)0JC3*i~)pxa|@RPV%b zaAFvw3`!iBPX77Zan+QqShsZ z(`5!j?~mlxvex1juw2E`lW#GX(2=u)m`xdIEthc6We7fT%JUw{F;n@d2VKEg8R!qG zTubkEw}n=-gz2yDgY{=$FkkocA#|&Al4Fab7TWZZda(p@|9Bn^74)Sh4Qepn#NLZv zkWHD$ID@Fh=$#utMZYZ}#SC{P*s_jj%`gRa6vQfzZB5faqxbe0Z0#Vju`tF{7LFFG z3bH)U2@#%mD6g1<-l4jNdL8U__OVTYCQbyI+f}Nda`yr9u^1+86S=P+;GkKOI<`Ho z@*k>ui{4P$p;uC{O&t$EqLkY@XkkAyhx+{on2u;Du^h+bw5nCOwJuP@(qBBv{gWy7 zDui04j7jhA7O+~!+Ox-)b4}#JL6nA*=q)#tcofxi4_oLSsFF>*w%H%?ZrJXytOxVQ z7{0ZCmhpOc=nu>N^oJh5=`qEd>IoA$*TA?D!pvwK8xt>82zZydzw9&Fclya3 ze5Ay6*n{r0x1|a8Opop<}^yWWjCvQYTQX+Qi~#^#gWqzQpYwkXo12= zr|e7(TffYY)UNgF*YfjuJ&6f73GA+mCWHj__V$nUCOCGrI{RYmmpNke7;3z;BcaHx zxh&@HKEMmh#?(*}E3f$bSk9=0_Wm~Z_P4z_I(6@gL!;9J)7;t}bx+IWY;zmMuYSaA zB!!v57-pPNbc;1PZ>t-NGN0i>0F84SmJ#A{Qhw$`?DuxirSRqMx7@WwtSo9ha7cf)mGsb-MnqIcXz$GP~|o2?(d@0+Ci7zv!0q>a{?owqja{s zxAmk39aoA!)Htbro2j)+wOaV6Jf#^@^1lK zdfZNdZEFLqu_u2W*lO1WYzepY))H(Rk=p`wIqN1e)-|M!Pf@Y2qhZ`cIdn}X@*9u8 z0qP|sJR>o&yl_rDhVrBM!{`B$!FV0mT>%6C`FJ%BMMfR+3!Y;RUY%^2-% zH8>N7{q2g|m&cc3`1>+&<8Tuz=?T2N6USIw!wc&+(hn0jEK*r~1EBZqh~cq*5G6gM zjBW5%zU6!|RBjJgsAK2n?~#ui$k~IaL_?@J11K4{K`$Lcj0I?Q3k<)lX@-DoO$&oI zZhK_kNB4SgldrPpLNE+BH%;JcmPvQqS6oB<7n`-jJunct#$)X5Vd=K_ zG9{|PQ?`cm7bDmy%!pS}@~HMY;(g(f5oqMP32%P>L}?j@%zCk_*n0T_RVol`CMwZ5 z_J8>mSXxqoUgEVS{Q1`~_eJ?NIoUesY$~YjYyhiOY`pjhnS_Pe;4MsB8uqF=baq#j z8s|YvO}?1tC7v4IA3d2=%RR#HU>(%GUF_uxco~ac2y9tir)UIFiRsA4ElfI^lt@~B z{xh)LR3)YeZM<&eK0SS}a*>cVhHBsVS-^e@K}h|1*~<9+i%|z+ywy{AE3AUN4+D@2T3TEIYTiw+8}k`+(^LTs2W( zv^kr@>-ezbS)YZ}k6`=$`LZ7Zz|67TUu@!#`R}~9+AVO5R|^$f6<08#u6_P}U#)uW zwy-`vi?P@+a(3c(HEK`8>*@NnXa82zER-oG7foWCwULL0u`@X#Wn|=fk{ow+->HSh z6NyRjC9)6RSOK`e(ySvpJS=(JMcYLt5D}>L!B%;0m1kCsWm949`pziaZu`QG5IYu*5!(;~vKpHGx#)-Wwbi z94L-DXfG}z`}wz+2`7;Y4)J2Z}N004)xp>ss zg@S&M?Rj7;d6(>8y|6-sON6_VP-J$z^w_fdq8ErEM`~q{kU^0ac1Uc!Ff)dlvD2e< zxpGOkrN`~eWUmj>`ho5I$NW4Y`G3cHM=f-^yJ&YPyrMip{l|y7r$+=cp$ra897OsC z7tf1+0=8u1LlIX}U^{?C*^b9v6HwA2~`fcRx0py%pD7e>= zH?E)>xrU}WfSMgaZ8U}L*H3}fMFlEcnWs00#!^+j9S|5eN!}E1?Z)^Mr0=?zat1+< z7u%Wd?_#O&O1#x*?|8Ym+p6Z^Hp5>z$n#p}wW|hEES1oF_86~+ZDjAVoI?O(@i3}C zKEz>h3fNqf!Iq)3BHYAlp59)$_Bpv@>7iX$5)Yu9@zCfwLG`G``Dk!Ab0l>UT7xx`^GE_ z)1xC;e)U2v5Xg0~0Odd$zb{S$reGgMNjV>E?crc^4ZBMVSelu}%;*EmvUE{| zVt#i}{_1;dm5XXD;26%al93#2*+;PN^!j%hQ(K#8W#+K{+f$5dHZl>f)^E5^G^!6~ z|2|Mlc>M^r7XjGwK6~k4`OlmAFO>RrG#8#MrW4$#8B)L8R) z(*s*SpW!Un(u3(|W-zQqRzO98mV*X6Y)(`-S@t|(tqnEd-(LfEmx1jC6#~7_$@K?X zYYn)F?X3cDvx{u|T|WD^@8;jOm(>1oRh1Kc8Yjavne-n(fvo3ZXUGsi?ASy2K480r z*4S^DbN&Eqz5Lp$aT2QRhb+HOThp$iXncmEaSgT5bu@!F(Fol}RU1IT8bIE?jdFZI zz_t>;ig}&h+yF907{v!8Sb6cQ8ti27<8`(R?0GF8GqiSf9;juoJ@pjDFGnzD-NKA@ zOFX0W+Wru}g1K)-&@D^?8}llpX>Ut;dbtg5Tk?-LfbB(~p25n?$C$kv#WUk3rriOI zn>S>;nL7?PU;GFxl+<<2@aKKnwlYuISMCQw^V$m5zx@h}!>r*KlHW|#+k$-yC2Iim zyw)8HP1`}!ilJ$_VuW3)_%z3p;gKWNXs!H zH1hf($TNJ5MhM?oMXQ!a{kO+RCt{cwyp4)$2vkY<_M;&zzWfDkZfkxCSX}k)ao*p1 zK8O4FIo4i22P6!TfJ@_X_srj~l_t9N z0#?VKNFMV`a}d+UpzK#A6~z-fg3OO!;gFMSdR=xly>rG1khhSw$G&Ate*a-Ejm4jT z63@)@!2y(PL&Uk>1!Uj!9)==It=Xt0UfXHc#6-eH<(n_DG4UE;4z>UNKH&0t;GmAGQ6T`S|$#JiT0)po(zq#WSEeuNDJ$_EfvI1#GT);Kn|APx`xqTmg;8KVu>` zf@cF%d%u{+wrbdd?*#D5k*%(vT`Xhf-sgCsNAW6T3DnL+qL>Lfm(p0YV>vUU-p>dQem`4|$21x1cY%e5q`EY|`yMm# z6sE&A<^l}Sc2P4@$DY~#(BsPwKUUsY1!W(>_B=Sf$m@R#uzlCC+dt!dmk!pK47PQB z019l^M2mF)h`M|yU`ywo54QBsiZ_-XSt<9^6%bZX%g|4Tig_!3T&Z2CV{Pmu8b5uD z%)?anR`)`9;8sYKm5T~x|_g7tavAm%e4I6INoN3dkOh_b~FlF zkV5$M)X@wpCquW0}uO zux06~W_aKf*cPL=P_(Y19{CK7@HJG!w~^NZm~jovBx9INMlqF&VK$XSdMKf4uci|6 zcs3PB=57j^dvWCN$B-G)F>BvODH@crI+^e_%(w%{jF_n0i=#9WLoQ}x&b34dcq-=L zg{|YM6~W7>j_J`TGNVz+(VcaJ$VG$VRW8N`k#`3%Yu>_?HGmmc!F}K9xj+Vn{|%ytD-RqH`NXdk|%*VQZjjTBsW?YPtn_5hxbL zzY$!Rd)v@$GzEdovTs0oI`(sRuG-w9^`EK8KXJA%f;FH!saOH7XrVPZH2mhqX6 zr!X^g2UEj$@G_CWGsi?a?nqeeLL`E9!$dt0K`t1^tQ(cwtmknH&l3h-$4!jIOz@b~ zCS7{MUCfORBX@rk>5(`l>PpN;*0nKdX_!f{Z@Z7zF&AU; zs2uO{p(rL&4km|OOr?}%?hlDKJU1LeVaP=_;i4M1Pi|NQlHDnzf zIg7vDKvCC~TJ~Gu)(6=0+RFsn67%y+4e5l7;^?qgZsZQ~ckdzh;2|=fe~y_44>A4l zbELoc92w?m#}arQ(lHY=$3)#n3Qb45u)0=Pu?RJV55o1Ek|a$T`EP#qXeGUJPuTP71{^y|yvb zqABs<&zTPLsUeg`?|~}p?3-9Wdn}p2tJI0{d3yA&ERtknDS_IB_=qebR>KBr5ffG2 z5TQCkt(c~AY3Z%?!ImCdKNR_-Ri4~hViajBh6z22=bDS(^ccoc_c1y8C7!rLc##;z z>!CY%F>(jbhDY&q^bVen+`(`06rSkp3y1JJY=b~sG>60kn-03jgkxg#*q-wGoyoB! z*!IIMy|up4>-);Eq>th;dhN#W!iwUBoxsaD_v;>hG^2PDP2pAQE+!IpF=i$(5p-og zn(io?(GgVKq}1zu7S`~qVdGgcg{Q+q_&Ju4-}O8-f)~jYUJVV)LddJpVdI_hTsXMUL&If^Ad# z7YLSr2C%;CHZL1&o5mGf#Omf1(9Ye)nNaJqp~wW=bW8&dS44}HV9Ov@i4gX*pH#-1 zC$>PS?E_opwu+~gFh%byJ++4|?C0i?`QkqE5AI+tL@ZBR4Q%+!Clw>o-K4 zY0(Ly9J!9XejPdE7V_FH6e0ttXe_T|pyoKJFgGd@MLKFp*y~(0f;nptGm-0ZKFa1T zWW&q>zKMEt02S*t7zQk%qfs3hSC`LCM-9-EHzV7zl!~WmAREyXkQy4Q1Y4b@j&7pl z4oE&FOA;0Jh$md4JO#ywj)E3O&KN{a4~j^Rcohsy;Fuyq6^l?zv7wNZ@*)V$875|R z)#e;qepfvi#X=&6YAlKjL2JknxO{B{k=6zwWoCjmR0w!9fSfac88d)6Q$sdlVJ@hn z98=-SMGE#Z#=P!s~VgATF-%5sAQy3-+0%^;| zOvJ`SK*#F=1FwS?#v)O?Hj)^Rj$$Hq2NU)%CbT5d65^~%=@f4m$lcJ?aWJ`^7{+Zb z+@>&|9L88;2(P0_ymF%Q`lK7fOgt%z&@;&dCK53`<(OnAun86WjASS|CFLevg zEE^N-1K1y!G0a#|OgPH;nCI=;?I6a3YN2bEInQPSMaeyOWIO4Ii&@PDTUtNZ_UGPS z1fnkX*^gj*vE$e8{XTj85p2(f2LHv+&jr$V1l|jQt@fFe6-md!?+CUeUFJL~;yo6` zA=G+6%RHK+S{dc0A7X%Fc}^|*5HIcfO;&9T9o0EHzmK4%DOdC-~H^p+lKZT zRQ*$m553t4L>Do73ja*=%iX+dOQqss_!DFY{~w+QKfzLF5UG9V$hc}tTrRoPGg z`S2hr;h+FiT?>O&(LyL{K{OH$a;)oW-bUWMja>LTD&gx`G6%7&-@<}^6Z6JRdA@3f zu%>HRibPNw45BzNDBjVM8J1i|f@0YmM8&v?1@jhGT&gwS#Jqh|uD?p~3W~QsMKN#< zmB?)YO?nk`W&~MX6B93+P8iZr35GBq)-bPy#7kWa-$22*fpT;ZrDzCwGa!Inw;6)W zP~@28s8(&$3sKbt0!x6rQ>%i#cWOwt!pHG$p@v$&O*saMlY zygn9#A*`7un&!p8cF8obsPP=?0?PA_i-reN%qu3K7cCPdn_flVI~*2Ic*P9K^+^vc z^JytWm1h{f&ZvSAN=Z#bz~QkZv#un?seZwOUq2qiaxJiVxH962|Myc~k?-VqTA;I;ex!7_|$SLc!8vgxZ|JR*6K>ODvw^K2>C2FJQMK%zuHJ2%AHnwBj?)RW zzRUYB9c=62f1wt+JmdFYrv24m>*w6kb4xI+8Mh!{+g2XiJ-jUx`83!vtCp&x0#)?l zQXFTYf#s*aU@jHK%g{~C>4PX(gQz({)U2B*N3Nn6x+0}yn$``}!=GO0_|J#0U_SiW zTdfhff=2i=ys2$!pMm+yJTC9s`p1%y2Yf85;gL_#?-gG>^Su9W@|`>f`uSFge2Q}T z6EVK8XLr$1D?6)fH&b^PD#akhN$5`JP#N zq!Jct2^R~A1e%E?YRLq0i8$sGws`U~=516orJ7u4D01L7(z+(^$weI$;!%{7G1OBD zG=`F>4#iL&ildNPXgcpHlWWlNzT z7WFVHp#jwNpePjAjQ|+oK<_dkdx5Ir5fvuQcG0+n6=M(!+92xTTd0I?Nu5)M8JBcV z<<^LxX%K`WV0bReZ7mo9P%ulp^2SXR;$cxqo+04h8AWyUKB^-RP`Ps-l{7$FrYVaC3yCZ8A5*aF3O|#B{E&1IFV7=pFomNr4kjK{h zZSNe&LM}^j#QPk`hSgW+`#!z+Rs98}74_ydbSkoMAczNe# zSHXTc5l1PRL~$sE!cYo%D%_@0=UR^ajN>W~xNXZK5y9^4Z+S1+;{wbDtpB_H?GW-A z_RD=uyD?C-iHgKx(S+27W_@Uu-|>xqn~S<&9xOk{y2y-#@V9yPd-$Axd!Ls3RdnLw z^(#6_iPm7mMkzLe>d-yZ?tYH)od+o1RmT3SK6DR_#2qy3Apt2u?)!l3+4mA`3i`=5 z@*!PvZWo*cnsP0qhE+2mbJ^0!6rBB!MUC>#1Hii2_Ff^lSwACyWV z?#+IyFft+pO<80qX>sw+zR6?D99xDVfArX1ZmFMq(3Y_9cLCM+eb4_{)c=Xg zvU&ZJW1u)s9O=(~{ar(r|4#4wcN`N!mDCY61~BD@fbIs`*p}+FhxE$Q0mzcI6hD<< zV@gF)`BbT&ilVNkMJ#H_1Y0VQW~PxIiXm-EicnyPA_z14V*&NF)EvQ7lWukMMm zYESg3RZUPFdL?jrQen_rfS`)4Qb^|cliG5Ad0TpS4|cIP_8fC|L_%{3rTyM+*$?l$ z`G8xpD0FlSB~t+|-%rS6J}i%SIdW4xP&4`qNjPM1MC3UX#?8_ zz!pU+c7UZ_V15I$55B^0!7#E~099j9Jc$K*--buAJ2?w%d5VctNffalPZ+5~aU_au z?c!*qf%%tD(0u$QCX4|Aht=pH>Vbb@-UDWq8WM{PVBWK)HUJu7*0-j13pBo$C5q~& z?3P48`0uS5gyKQ9--ItCD3C0mtOaG8^VV$?LjOX+xQ0?ZglT&aQwa-=AHK!rg|HYCC7&M?kDwG;iTS9;?^raekBW{SA{)tiYJt^h1k3q*cGu|Glbx z8!Yx8my_@Ie?vgR|TaY-br* zETR7M*O(oNOMW$lrg*IRz5aRO{_)t;DwYCoAHe_WmT-G)zVf$m0+&9B`OrmWaLFmx zl}dQUaWQ8Z5_(?x@&T4!{EDMy#Z#g7#KU;M>~1S1RrV3>J#I?S$AsTcFeJ>;sKhJQ2aEmt`mT@rw^ub?Q9kGIV@^Gv6X<6& zQ^I;1-~WL1i3zkR^h5C+5$B=eEbB9~`oN)5kUrQ&cWn`e)gq=pCtT1IsG}5T9%>A^ zU`T!!qYHRE39}#461LO#?xXqiDUK>NV3WsrAK0d~)ME#o{aziAOJ~3K~(Eec|Si_jF>1Kn=L>~sP!$cMa64Pb!0*=0hh+dd~ISNBH_-H z(G=z$Ji_YuwA9cB?_Vm(Q(1nGB26!NiOR_ru=fS7_kDjp;NYzmykt22gZ+Eo-}~=+|K)vq2+%tNwp5T}I;~XjAkv-&TOW%2N}ZB-d$@;odK$Tu3jeHGw*_SD##PA! zX4rJiye8hhWA9%0nm`ai=sc@O)Zfmwe7_I03qb|8{_|tV4c|aRz?N`JpzXJ7sD-bf z7XI{u+p7Lg(CV5pLM!2QA^eHhVo0@oJ|F(%R8DzSyP}{ra!tIWENOGrc%05NdO`_% zjfW#ZdksD8fK~cL{EMoKd?0+=l~PQS3oXTh0fMaxUMAV{y&l-Ue(8ZNJ#z|d#j8!v zHoeQo`=dOugj!MY^}v=;OHbx}i0AAEilOVsFpoQKV*aPEv6-Dldu>5#r*;n8s>CNR zB8ocum7n;Suk8Ulg?ZF}{6#!`d3v$zK~(Rhu=4yFu(AdmbkOZ~r53QN;oFvi^DN`u zM(en&Lwl))!@>+^Qx;|;*Cc#+UcV|}>%;2%wsl>BETbMyYybkZgxY@76<88M@$<`Dv3%AxI?FZe zrN>biO`w*r1@`9kK@V)zeyTk7L6rw=22nBzxe8(ls~=)MY+g!x46;7hzJL26Fnjtl z3@^TjsjzPa=cmDTI$>b-`LEc{Wzbt&2c(v32VJ%-gTn%BRCfjITT?B43)or4dTtWU zC*OL?CYzb8Eu?O^BLAL*WXF-`T>qC1(S72MR z7IKq-!6q2OKB*zx+r&qpdbq$+y zS(LwfjG4p;igxM^P)pENV0+TOAK3bk>qF~#ZAo|WHY1$A%>-;2_UeJH@4@ABswGc^ z3=up_Kl}pq=g+X$Y~rZ3qXZx2Y#qt?rOM%W<Wt0rpL1eoJ!5{9@c(*AoaFo?XD=xRBS&NXwBch zEZFk>JYQtOzoP8N_x~J11#gFZ9pWPHd-f1ZvHcXVrQ_^MFof-A&w({6 zwH3LZ5n)ZR<#j%)@!0lEu$V3+Ox+Qw(~_p(OW z-1tkIDE|Bu)6O8`GwZm+@il8W!OV*BTm z=Z$N{_Ck)(|4v{l^_oVV=DQvf>dYF>x0h6$&uUv8U#l9|x0dV9|HZpv)A7I9vVV;| z%S{{%-@Z`nT5by*aXrkGT`HEMS{gN&ti_bnTq>Q;o3bqh?IsG^Z3%Om-UqKAdYxdK zv)@DMVFYOGqJxuj#g^iPIS@7m7++ekrJ_rvl7J>qOH(H6O^Gdw0^7{MO(ZS%1Z=TU zQoUsfncbGC45seL!B2++bTlL#UTG~R-Y}V6 z-Jw}l!kS45Zm@!*wOA_ zT^~ZqaTiIS3rCZ$RUcUP5M-TnpYfO4P7Yc*m}!E_j5Mt0_EnB>^z^ZqC#47IGHu1S zZ3x@8{`6|9xIG$m4JR9^#4`Dh@6VA>d?cWD%*TYe% zwcmgC6xiNWJuX{SV}Q+lW*F!ZY}+k#8g)^y1N6Y$~=?ZwYa0p%}8!7>d)dwFpEuwqN2qJoXV8r$>W zbAm0+kJzGW_vLGVsx~KM*-3)?0d4cpse3hn_LPdZaoulsft@34znDeb9>tzENy2w-(+NX(%W*ebZCqx6<-$OwzL6<>qxMO51U z_gq%7WvVd2Q>7#qbPHC!7A*NS#Dh9es~B~2Ep*#GnddM|2skuuut{5&-zBBlwW-__ zXpVL<;dM*PrB#pV$gI|twY6D~LsZ+pyJEW$9YH1-#y%CzU1m9)0(I7()|DzGvtFF! zli2{3!rdlVP%&yso$_%aj^xNF*j|Y3VF;Tv3{thfreb?umrUhW)gqspF^WgXZjd&a@{-8LO6J+zlHf)JI zu*(2jqn?*Fy`K>RwoG|8z?RuEy#BVk%$iX-GXz`OQ8v*Q;B9jPuH8awV;!@x5qt{R zsKo6&AwzR@y8X}PXk**tukR!aBG4sTOhH`&EBhVHCajUlVhk9TVqZF zU{(&nmNmBwcAj9l!9fMvvbvwrVGT0$T->rd~_1G!)WP-XmIg zWz)rws_2a1OQa&t+uV{;elR(!z}Bqw7Qj{$F2<~jf?Jl5gm z5>i>W%UaU+g_sOE-mJw`+h&+*X>S`4z4`oOifupGwsCx}*!~Mrk*U}!^QAl361DbC zu%(d~Q!LqLg*`>FzpDVO)kd==R%Ba_{j z&V{@x^;BvWSxc_Yfqt-MDY{vr&f#pEMoFCpaJY-t0Ub%dSNa1Bj2Y_iIoQ&~%Y?M6 zT3)=yR-n)u6qn$g=LFkrWvE4i8fG+baNSjtL0v+EscxF;5r3zCioN)pq{S|<@2W2h zwiP1SimP?sK07zuGLE@nDs@q)HNlojB!QADEx}W%sLG^j)gQug*zgqKn*&r>(W|C+5xeRkQhaM zetj+LaoH|t&gMZP6vN?kTp2l1g(Z}qSI-#ts53G7T)h==KSuG{7^b~p#PuMSv>=x3 zY;&aCkJ(;HDYix*VFPT7Hcb?AWpZ_~G-OqW`)-r0PgQMAh47!XyjE7*Ah3QY=t9e%pS#g2XnY$`OqW|xsi;&Lp$7LH;PbV6 zqS#978ncDXXDqq?{5$-d^SFa8y9yKfO!wTg?Q-4v;5MH99{0@$(zFTI?*dy%aJmAp zHQ{#KdRyG8*_ww2MeK{pRwa^FDd|&PoOU>iuO_O6&qRSVQ`&gbH~#TPxxJ40pcPZL zud(2}i`}swf!dL{oQhIQF{ax=o61#}>C99#)WAw+#Q6s}Q{Fhm_KT-TxUEQQ1K9M^ znfNNfb_lzc0qom`u<5j6MYCZ!62u|hkXaMeCDc;!Q1HU#*?v(w%@`O_x@(CG>F)C} zWY_{^a0n$E+X)e1Rjn<*1Lt6?lw0WqYd9o}r`vi^6w6|OD+!<10n3a8UtutV?u4OB?Ehvkl7Q1CAp%UNn{*o zcVypg&CX#q62rVNh)ggl?#MaKB|W6gRB>q+rJuJ-Qs<4Ty}b@$PvRW@ZmviBGC{>GmPv3Sr6O z#mXT2NMEML)`z&$hxyPb_NM3M^QG>Wb;IWMh-Uzw^oMzG=e+FE335+fVq6bkmPTpr z5SD4Y<C!jYgj)hGTP@KviamolnQ#rZm#mS!tm1oJV|!g=`=x;ReW3ceum2Um z_8d_AVfAw!pSNORn-#OYiE7zmrd_I~4C<|hf+fpA)t1Ko9oFnOu=bftwjkPZ+*M&8 zQ2kIHcd>1Tli+(xV%>QQYnlqG$fjc453%oh{2{QVs>~W&x&$*7*;H%=Z2twW$W(0m zQ<2SdWG<;-7wiLAcF^?6j=5L>V0)i>O=^FtT~^fggDuq+no4jG)KR6S9H}!ct5m>Z z$cd@puaSv3a5VlHs2xiS0jgMy9z)fa5o$T;Q-eG;BhD0MsYhy_Vt;Z>dVZ!^&*&by za%x-8g!ZcXmnzkdz3W`9wYE=+)W18iAe+XuGw4p8kd z{kVflm+ATnZ24M4+-Exm*zRB|7DmDVTh`f{U@OY70l0s6uw{zvQfx%Iq_fn486F)v zA{+IlprO+FxLREPJ3Y{}M^gG*ZEViWN-LBZuOF+S81lY=^v^BoOf^0~E<85ecjtY9 zzYN%(L+yF{9Re@GHXR5d5e{PG^()|DS4^5{9LH-M(|b+T&s0V^t;e7AIOWkLaMn;+ zoX0{i1Wp3vb=EFA#eJFSoTmDEk)?pGv>jrdKUH#?`4MW_f{2dyoObD=&fg)}@^!YX zBG_*3VktcOQCH*-fvu#fe#Eud1l0E}-v_Mb>uIYCABuigWD~MkTT8W;`+M51VaD&r z;X*==1=EnF-#pql>DIw#%)pR;R5?3cnWSZ{be9tZttOUVyu@o?1XJE9Cc>lW?QF}p zzS2H2Dw$P=lEPW#hHT#d8b&Rz?E6X;6M=}d{7JI^t4*nupX-Kf{yr7k1$Pkf@F=z> zX4SDZj2!u$<92asqyPISK3Qg2IAOO^6R;g~`7q=5V@VGqzDf6YsL0jvHg!xZ2JNEb78js_X)N+Z2J{?uRMBCeWVOq?)yS=v&L)wd`Zd7&u!JzQo1X{;hIS{@f+qm`$@J+im3r zY_z)(6DfysO*Wlx*R}7k;ktpc`v&-!4#@?E+!=^Dgh$c2fJ4m7Afoyfq8P)qBJ8oeYWw~{qQ z4KaISx-EH@f{NT3%Ntk->6p`QV3;V$1%pyABI-_il>;QzqcSY`}+&nF%AsuMO5vvWkt{ z$PktLd>katt5l;|w{+UT@myS7I2RpuuNjG-Pe zwV#;~QfJ#}Vs}1)_{c-)#hLOcWi#vY7>eyb7i>+SRB6a>f-U>R5^QID9_&m_sI+u3 z-s4rFjcU6pV0#X=O#7v26VC;vsj`gY5Qm9bq(<*!(d_|0lg`gHzmi(T5A=dPhst;N zie2&rm14`3Sh>DZwQVTHmIDVvbv#pS3BN}M*p@diABKz-lxL(s~fz3+W|eZ}sUdQd8iDS2$Z=EkzajfCdLj7!J3-;16293T$;oQ`P9 zaXRXrq9!%Syj`ow7G@qb8D>#Yr-|&;6n=N;81n}4G8jf@e+R8@Rqk~S)Y0rQRHhQA zbb0SHgMch;@Hn|!t>T3@fN4F1gwv13VVAfHo1pr+OM-3E7r|?95L;7oDl3X$&XORx zClle-P=vQ~2Cq@(V|h}kA^-H1D7Fc27%RRQRx}@0Z0gvi9WL}o)}|wG)z5nGUbSNT zsVU3v`@MGoa6inZhje@}hTTYCVZ3Yo{|c}D$D2p>gWiAIK(gAt+ zTa+!|qC9*9CCj%GMeDav@r|g!CHvRN+rN^?+5QIw>;E8c`ERUR{zrQHen^%5(9a0* zS?2(*5^T-&quOllTc&6ey3^V{EPE}|w&Zo#r5szE$2e`Ch*Ks(O;lSM0x_jdr4RDP ze#*`VygRa7XL}3rh>mgF4J4y3>`gusMF36KZke!Wrs1h+7^dWzU@M9(Q{?KW*c^X_ zS+4_`paUyT#Xh!X4_*Fk#x>Ypq^`FA zJr}RBr2)}-Dk^)ZY66{16JGYY5f6F+)+Dling^MpmrOLW=DLH^RvR_rJ5a5$#R_MM z>dF-9! zquM$}z1tSBv(9e?uTc*m>k(;%@k_N9(hKhNkrQDJ0QWtErrs1RujRT7%O!IsJ0d zYk@gTCiI!$M-7%!v#en*%+BJaFNoK^5T58>bapn-?w+91J3>nmnw4V9^T8~^F%?_Y z?uUj|1lt;3`9qk{{Frz6kaqgN2-r^f!U}9@VA!mK6UpYp+iAN8CXewsw@tQ>8P=kV zbbyl@3Ito1AG0n$Qf{T#QVFLqSjMJd#jb*nSFLX3EN})X2iOF6C0iz*znvEuzjB+^v7SnTCi0P&s5FtirJT> zQoGbP<(;>XcHP0UK8U!_ikT4)&^!jZRkT_sXmmLQ11dcgwO$kT-YKfRQ&f5_9Cm>d z<8Ij8*~D~A#~+rjFdK1Te|}7yHM`B08l-aY+HJ~UmaQ(BRZ+01xN{Di!xmLlXR0A;_FD|4 znC4fj;$V78U?$b;p_L8lJ z`1h|;v3(P4RZAYO4^>;%#Zqkr6q=_a+A7b7c5c8-ZEVo2NVO>I zJk9H_S`X!h%*JcXBjWXo*JP;??zB)X6)+wOW7)0xma=#0o8c9(IqyNMT#(;ZZq4-H z_bopJrkDL0!In^))Vu<+gjo}C`FO#lW6J5mM8JoG#JtMF>9)|2ea38@E^6pVCJrZE zC~}JlA{ASPz~P?gq1D!bOkmIjTimGWNZoEq|JY``0fy8$ z(`cx`TCx0{j%s6MDzk*yxBp2SAf{?n z>ezTTj!9PlbD9s!S`cX`q1KPQ!;6gN%~bG=MMrj6M{dX?aapkKhoQg9<9@LH=;O=Q z$X@dOf0cdq_Ig}7*lswl7A%<>`ge}YKsjqZuQC-`6jQ@Zmxe=cgDq2935#a!Dcyvb za-21S;8@oF8|&Kt#io<-Uq<{lHl6>CO~?OWTl-&ZYhN4jEw;73aNam`^;Kq5Y+ZBD zc{pIO+us)|8uZ`vjflkr+L(Mo@L*;~HOQ+ zC}Hlt2hZ)_ARe`2Yx=25%j#k){r8G=Y~iUBf);_y|YiV@L%(DEOUn z+^*6*ii+vF-GZ{yiV_uDw^KmmaN016VcH>6{5Xg;2eQm9XKzk|EC&!$hehyd2?QNY zP9PQXVaa7f#%)2yHTWm6Rd8#jAYTM%&)@S`fYZyY!x`XR*d6)uiY?(rwU$vX&jpe-`|F27xL>rIvM*;J|a0<}DEw#t|d`On(@n0;(bxMgj# zD7b%Pu+6!3q5BX%+x>h9Y^g|R17XBH9&E9l(cz&=_2mQx;g%B^ z;`Xe1qY`u_?bHNYDyg+2?9EJJAshiyhq-+j%_}OH$`*Kcn(@b=mOmG;J!PFID@E1y zTlKJ27)x+tRMA9@%A(=o%WK+6A&2;bhgS}^?*n4<^$)@C`xINMwhY4UoTg*S>&5oO zq)OYC>v>c9{i>-5BSlwIkGkmbT;(<0bTe+Xu=?Z~#+^RQXg*AN0>I9uOb~ae$jkJw zar{{h#tGcM=v3JH$~gD8_K*nQ7xSo;&5xB~{Ze4NYWHH%>BYQ<=53R}p3%pa_a=I1 zFw?}8X}L+9grobjIWNoa;@%Oqo{b^yjewAx*4W23fV{&m$}GXQA8rY?4EEq9++Kt2 z)tX1W4U~VC=ht9+4YpTSV@t3#(~$d>S^_Q8S()a#9kgOIWJNh_MKLsttbYKjzI(_7 z2Cx>mhdu2ZoY=oI;u{>>8Q&Rk6DN*aII-U`;x10?=W*y5z@BEqj*H>=?BxdQ;dCof zUc1DS&k70uFqR~Su;?8?%0GY=-vH8{dq}x%BIUe+744<~Izj#Of!2J_)q*X}qoj_R zZI7Hvv8G8@*>Mv^hpHV;J8ogcH-yEI9o6_tV5bPQ=xBV1Ui}z^Qn~;ULGHd8Q^`e- zH|mPqtYwy$|ErwfXfcjt)QPx$3(H|E%8wtSvzAvk?7B*SQUg7zRdj`A&6iR4W!}{H z4$)i9V)K_@kkstRYZm0KN@@Sp)Z@2*?@Od2Q?Zp)WTyjJw+m^XN7fPfoT`g6-uM+o4MU5DwY>dMW!2Z(H|7JUHj=rbkixN z+HxPX8t5_YwL#UZq4pd1-6@UajQv)rpjRql=k+Twph|ju$a#Y(>3(UsQ_|SWRvlj| z-UM0+{$1m^UCI$zKBvFc&zm*21lvM5hDDzb`JaA9H=C0>N!7EuW*qybx<1HcM^jCD z(J-i06N9~WDTlQuPo(7xThHV@K~X|kt5|XcM6u1e{kTYQBA{Bzp;0?fe^(~ln&`Fa zq7*XIgsHGGrlx`Y zEud3T_dD)WxzF)j;QNdTFiwK;oacnj@hMK{Q(_#o>by{pzy=*SkNO_c7+tw+5;%r z{KyWvksUU{R!7=OsP#zX2Ytv5`L4nCl8P%8@XN$s1!Uh|k87~K2HPtITc#YFsmG>S z6oHnoM`e}(nDN{ZkX;GfL(+c-3GXc|_--TRy(6i-V$@_eOsDL3QI;4$*-oRV0Td;M zP_!{DDA+8r%-b!_}_Q&t8hc=5tAE>wLfk#$1r$G{TNKzZHpq70Y1QM7)__?Rm-=MlDy!$i`=6i z8cWl_F$d~LK)Y((n5j4(1I<04u@BUle#wDZ4O_D_$b3J7r28(?&TmBlUk%x@`|3G* z<#jbkq&kFA1A)wi^)orCR~+am3FSZ7=Q?HAM*7G;1d14dD9je%_c zxxmQ|p7)gloGc}<^5X-{dYxyjeh6sm&hsGT3bg%=6A5Ah2Rt6@GU4zR*t!iDYok5R zKMQQBe5Dqsl5fK4{Ht|)?L9%fvqUO&z@o@!wH2G1Foowo60zIYmK0a$kz{!QA?(gdGs?T zEE-l==jrghBUHTirkDt>>6%rEzm|Ls0Xzdk_W#|Sbp50(NBEP95qtYSGD!;-^-g5^7G41b04(AUUYZy^`(W8?S7Xy*#37uV1# zmCz{_MSvUu-hGRJR{RxmrqPv(vYdM2PdKL9-4)uH^e_v^3NpPNS|okcBQ#A#^_^|dliOGR`xH_#{)P%C6n z%dTL5aSo~9e!x_~jfH@Yv{$+M5@a`>DhRm$4q(fDx2}0aJ*DAO@%{tszj}qrVgi+w zH0q@ynuRqqaz(VVCA4#E=;hbZ$(C@syo%$6B$EGlghV8SgvWzrw)bILI6v3v#)hT~ z;7TpD0knk8^V(D|{@Gxgar?lQMvK7+Rv!I;jqynwF0J4sS3q-ZL$(LGb+ig=aviJ| z@;J_};&3^MqeKFUXbeeTNNPdTb}vcp20CJmXt(H+s7tzXZpp!47wVXqBB7yRwKS0$mNoa8Vy}?%Xu=Sk*ZQ0_1 z8H8Lq*3vbZW=)Au4CQC9QC-fUnk%AGDC2Z<5A}@$^vZ|8`Z2J6fM#wTdkf3h9G{Wi zwX;J6&;W`9K2a+(?f^3X_y;P<1-bt<^XlB@`Q6QJyb+Z|2HP*Ek$v<#7Tqx<2ffG* z2Cy|8!q%W4#o>#CZNcJ2fhJB?FH&|dRsti~dh!a#^Gi5g$)TPrp^;xlBU?r@vnJ<5 zo9D#RD)wd;urW3zsnK)J02Up7q#Z$lI>I)=RzBOJ%%V(q%UQf&6o&lB5Bo2z*!Dx@ zRXlzd)b+2&yMF%0YgY-i{M%m$M8EXsTshcY2F$+1d;bb>dYN_jynXPkQBV9WIH6E> zU2To6)Xy3z$3^X?VWgz$Q39HrT9RsI_7mM1V>Zi&y(6cxMs(k$bsO>3r z@@NCt$)mM8kKKtU$o>?=Qp_!B%PGelWbL<%xbco9UwdENLe?>a>?qs)>`7x7b}?kR zj`)f&GmWKWM(Y4+_d_Ek_K`E%HF2_7oD-QI)u^I2JAp-y9T~?x&>V_s#r?qvi1RSj z@w;z;?XLAEb}TorWx0Vp_dU?XI6ZDDsOWdzv-tWMi z&xskIhG~x%b2?2qoXFXRap)Srq2ng@tv5v#&e(>K^0+bK)-dMPG2wM%(x+p}=aQJv zU0}?3eaPH@fP~wNMF;C@HI(dD0ozRr6=v1$hmcAmsiI2-ANPano3ATJZKl$j@8j>Q zU<;vlgp-C%e-365Y`E-Lx6>Wjh7GDk9-kPztonjT>V7PE0#e5`?+atrAI4NLjPXcB zVk#EFv_GIy4RswWRvU_TySObEhwjLv11BE@aK8xHvNo46tZH=s)4^7H!x{!ds^=*| z^3%dhYh|q{;fV?=Q;}6VvO`jclOA2#Hzgub%tm6EipDTCGJ@&Y2qwZ2Ooqak4uudO ziDE7m!CW|iN!^J_+Yk!Tpg3cj^|fa(+qb^`>%jG3Fm>4sWjf^+&?D?o$>h57edh0& z@9SS?b$-ry@Mn@be3o`?ewKQjKQp0`OQ|nqjj0jl&!jHYNCj2^s$)y{OMliCuNN!P z5zI%TvR`IK9$+jG#kfC;Nq-FS&;u;SzQ;oBA!dUyOnCfQj75+P`H}JZQ1Wyz&5A#|ODXR~KAum>MI_tI~2^5y^`LI6h7sZyfvYhnj558swUq4H^ zwyXU@s9hWOqI^e}&q)oqFf-u9l;+2TCx|gEfN^&iQ+gERS_or~0A4$TnD)dlAGoi= zJA!5ZD3-WQ&M?Z32+mTB?Ez%0UQuw_R>+JMdjM&B0IRl;#ELzHltTp{XRRTD-Mod5 z&mEJ^THIBedcXOzeu%t^$L|8V{`Gj*&)<0M8f@PQ*Z*fj`wCYXmw~$L_kM>pmx@2{ zi*K;5eS-~WU+`G-x%L&doZn#Gc~jC9ud0tNO`$T58_2nCqNLvfU5?j1w~*6sV#fO4 zNZ)s$viKaW%@k1I23m*8e5l8I%nHyv0$5KZHJW_}3T%MN5Tl*GB`xOrgFlzw?SJnD z9uo?g0%iuEbG>?X^x7xralKhT+C2pJb2v#&Ap6HCrd)TCb`K)!yoZea4l?#zSaq;& z_6~CPy8^jy_T{DWrfQERUE4W;tiyurNEkTXMO#^PD6l2nvaCq}mOhpA)8%?`n|o(q z%giSMVeZ3L1=YDRF?(Vw9HxU4V*6Ef6KV;&bk#Q3hrh$La@I=I2+RzEW6^R4CD#xV zL*Jo5m~{+d%yvim$xiEb%($JHadT;tm~-1Oui3Hav`MOX!8(XzpN8VVH`sFxDnl{P zkhBv@>qAKE7O189n9o&+GcaowT{fvXWo<11Q;eG&gV=QpV$FIRY0Gy=+P)LBtCahm zauL=B{15 zEja8b5^ObH2G+}VCz4J#mRuez8v`*8qB!8A+vciPQ=Tl4qcT2k#K)EcU1!C}SUI$Tak0cRTc=SJS; z#0qPpy*e^34QWk7(eDRcbyu7&q@5lC6T(Tx#oy79W*xN=DYpv?x(7=>KUQ=P3LY=E zeS{Ae3Kl!IJU-CGi0SG4`I5&cX{n3e0Fp+ebRSkEIN0~7RCc#ZL7B^mb=HMC?brzT z#QdmCb<$~-c0#PbB@8aP-AFn$ENLz*`@C2Rc#!bBvEb2UyYf~$PTW514%o2obYs)& z!K`BtOA#HJNC25o5UYUzGJZeO-T;=p{`2*t(in`$x)U7A-XPW-Zme50Y&$$CI&^_j zwxCJ5y>h;DJD2?-F>~T}@-feOn(^d)Ar!srd+I^i3!M;be1<~BdMn^I43u4US z##|tR8BZ8Fg#5B? zt3I`DJXYNQtXECyUM%|DSoFKFp^_rMoO)cHI?`ewceBKML3_I6O$Y z14w#;XR+i7U`Y>xOY{6n=suYgT=hp#@JCT}hp=W3U`LB!%^pO`;ZvXE4q-tHhyf7$ zk;eToO#3643XEVj`VdpzD5ji2q&)Xg@H|Ap8bx6!h;@4e*+CsSn;%7AOkAlKJ$}Sp z9!%Jsn6f!BW7p*R7I$cvcX{MHv*6)`pC9Q!1UXj_yY>)@Hyqe=k6_v2Mnd;XUt&64 zFX{nf9RpY(gnL3rx_NnBL0Qf^f?&iQVToB+ z7~?h{X1y^id+#G}i=lAOkD?_ikW0{I6o(1C1Yotl2)KmZHz4sZsy<$?G)oC|DrND`rE4x5 zk&E(3Ns`USdmU+eLHqctjDBF|dZ;dR)K8meqJkby02~3eb+oruusQVy=7M$sF!rJ) z&?>0CC!m{m+!MI{bgD`oWt05+fdf6n7R86R)a1i0~!`WIu>I-EQCB* z2>LJ|GQ)$#pa;tV9T}ess}377!vomT?Z{bfV^bfNwC#d^8#(=!v>BpX_IaGEuA;JP ztSfz2DD^Zqdn?ntpjX`VP6Gqt^##$hXTr`5z{V0-;Mv;2( zK$M(Cr$_oKasX5sv}4=m!sf6In^r5=Tv!X<$E?+bY4%wSMFjpi0T2&Fkno4jA|41K z9tf)bx4{tRy?!L9qB^`N*nHTq1W>Xl*h_iC$OK|Y`6F2Jhp`xpVJ;NKL@GXr5J7{F{GfLWg( zvmP&|bPpzUU4G}a%Y`YI8%diRd)6?v?|QN8ieY}xiE-V7u}}ch#x^GWY8$E4&xMrA zz3AsL9mQfKiWfm2UTH2#bKM;9VSRwx>Bp?yBiS-5z8IE$Q2}-;u2Z2HCj4Q{xPzE* z=ot3}FdYeF#_PwT+lO^W5Zi+u?B3I{JM2Tw;z45AiD|n_CSLfrsdUdey@z_JoOmrrB9Si)~CKNvUWchX^RJ` zA-Ae!^+d5S?82Nw$CU2Jq}PYnUOy&u52l@7fpsp&HMh!uh(<8!_90={QL=@wGZ@15 z4IlO`Bgnf(5Z8iAJ@y1K?+RhX6~&4*h?FIOC0jsXb=eaGgDUI7uvfsA>g&#(AP#Pa zP`(|+(mfxhb*lYQOz06&eN7d5+#AJ&FNSH)sKi|45hjD9c;$;?n)SYx2-b!oC=5rC z9%Rj~0^7Br5DLRg$q&e6z%|%@J}my70Q(wjufg_8!FE-`U-NLD?pcqNo?70fJQcf<%a=eJXUe3 zrE1GCTL+2R58DZ8MxR)xQ78Fc#rCfQwgR`-yV$hdMRDjh*4@gXcV_4o3J;^$eeoMA zvt!tsc!9%-G3-x{VQ*>-J4W#N(ZowsUq8oc&?{z0tIi?h?Dw$Yvw%=Zs4dVu>P?~#;+{=Gp z`A0t%16C~9l)`SRvs7)V(kiFuPg893KDr^>QLw30nm5^2?Yz0z!_`Rq(sX+(w!**;1FR7~l03ZNKL_t&$ax6B1 z+OjCNCfF*4_T%PJ*I@f83T|F=NP4@ZmU=v*tWwEajgDgD*WYmX>NWPqUSoe^0tZtQ zIGUNl(cB~|@oAjIXR$Xqfz1~$Q2hQUQJ(uGCurTbHS+JQ760qhZ74#imWE!1H!H<{w0ndh)aMy*`{6$MM7j zjwh#ZFgJsPcpNA3c~s`+WcxSAo*?~@X_Y>tX#%E)q>hyaO`ogSerd2}>T1~$L|F?9 z%;W`qN%XL=U9Q?uBgntmg8rzgSK8heG*!$&em&L{L2fhhJHZG9u*}o z?~J108Nmvbbbl0??|(w^`BQ99P2gl{0SEC}+2{LHlX6@)U%eDVtirP=$Ul9I36`wb z+$h_^Qa8Hhh+ulyg~?b93y*)p*3^t_+ri{4_9thtGczx-Ka;@GbR5T%GoXRk*`=bIupV%A=pK^T$gZyqLt^#2j{K6WEsi9k>sd^5M~SReFY!xlhB3rJdc`r!}QotQ*rZUOrfQ>d_Zem;Sd#4?T(DICqE zus^YY?PrtN`t>CeE*}!Zb}U;ptlE@fOEAqiREl!O>X(#VrtN+x-UYTijwyc(1+jY9EAYzwG&TAFv%mj} zmDjJZF+C&uhTk^^&k6bj?9RrqIWdK`Cohoy@pmzfqH4Q75X8=41S>Z^Sg;0>xc>uE zPo86AVisGkXR$jzC$Tv>hxN%h>`WviHpgaAdNF~?kw`wkS?ev1w7T@-zHkPZ&uXyRw! zWCQ3>?QDqpS?@HYJxsUTR?WxX?)-gK&&_^q(x*n%tupzyEedK&>R-Er+V+V`r{2mV z|H}icdL06`CeW&uEJ|S{-2Pp`mQYJmsm#DlX|0piZODy;P?>xQ6w<)a4zRthn$5G} z{1NMs`{HmHIM~L{v)`~94Ipm4i;Qa+YknJ6>^J3{DS9pkwoFgXM1$CR{T$8pRiL(w zUc+!^ZX5$GwktSP4$hrpbWS&LytRVe)FkpxzL)O}`^1`HYo;E*{oH*0?Io4ulE;di zeGp}vRm^>;&XvPa?7w`D)0HH!vjOaG13SCG-afE@0Gu2Frw2ftkN1Ic39ZBec7FL? zYS6NFr_@B2EW`4-RBMZlYp{K1%Jc)p$}}?5{f|um%&tJ zf-u$Ee#O>Qda33y^?4=WMd`hlyfe<0jhjlQ7wa-6`+0uoa_So8`27A z?fyeC9ok|$4x5I;NDRdnzu_depu7a=DNtb;UIYBB{y5x2WqApu$B(7;2~%ZRr%8y< zK74@PiPu0er>+InBcRT8IZ^%vTsK}DP7amZaUqBO$#GhWiRE#E7uty}7QRo$+t&81??Sa*db6`Ag}Y|WAj-$(A@_c&r-)e;?S**dE4 zc(Ij~97n#!^Hc37!hHGZQ)KTyLLq!#K&=>hh_zoIV}E8A$d`aE?xzFbnER+^v?i*l z{Z*~XzVBp8*ncsD!sxF^I@#hSf@MzxOkd9a_zRku3~+3CSMVHQa6Nd<(sSWMQ?ip#icls zPyax|=|@S6N-gT5D~$Z_PX)%1D+AjHz!BGpuKP_DbR(AbTNOD^k5`uEJkR(dNZhhW znl)8aD%$1Wo}k9|T?gDg{(bs?(D9xf0E|{tRrVu41vdAAd|BE&i7Pgt*5*{H$V?@+ z1dtvg%zhf!avk~=TRtxMMzQ|$6V#F^VD~`n+k*q+cr}zG|0%sU*mZ!*8mbw#k9vXC zz&|9Fm`d!pRmY2P1oLChvA&)~T{<4r)OVKKCoTERZUt3zDhFupY@%5#V)geYQX-HY z3Sh$;#lk%=@(+GRd1@9XBwd(GWTC`_!?~gT|xQ(tZQH4YU4ZnxjyvzwNKqAfA>`6yo)u9x3T8F zje`AKtb6W=61N(*;B@{OP}x#2D5gkVw0i7|*OmTn9kvg+;(ubiB+b;tg-JCeHy#pf z8$Fc-EDh|NCjbYI1g4#Jl>Yb$X|DqX_wbogORz1tsj3Z1n)u%tY{j(5HH^H+iPfNv z*4zZJQB;G$CZUn=XxubepDeY>%%5ftTHXk&z*-jDFMr3R{T@=f4TXRmRQU^@d&s*l z2exUqLja_f%_@U2o@2cx+TDh#+h(JAX*SOc0W~?%ZXb&&*l~Ih$3*rT=0pdBFwN9wGYGp3 z8XYnE!B(J_21v#_vHrF2=n<;3Gr$(xjqtnGF#6s$0kaP#zk@vY`TgthoU5Q)EMWV| zGpP?Od!u5?v-k8FPV>v?Rd>{Plx@5CU1bkx3F9+O?*sOfKHNubB_-*_%YiWRz6e%B zF@f4jZUs2m1KOwRd*9{f)X?L#lD$zI{0{In4w5S}A+|F=gZcX-l19B83?l#2Pm;ZW zolVvHi`Noqf71q})ePIJv;nro;Xs|Oz#28wN~_2}{R1m>nsxZVv|1|Yr<*18r0p1c z;no254CZ_Ixjo~$z|UpxV7|V&iPplBq~jL-1m%#l)iD8+z^dwH&rPNTN-qhvra6^q zMrGFIo*7cvy~sPfvTYep2+QFZHlIFIJ#jg?!DA!+XN~JGx6kYWE=zTubho!qO)ZNv z^Kxhu3pDfz-^Wp65skHy(SnG5RJmW-JD8z*D>wOf@3^Ol|( z?A3ZA?)+?hvqU2-M-XgdLsk1Ul~&tlLNVXpQs;TMc`6h2EMua%qnxMJsyH8K{_zlV z^jxsou`=XBZpb4BP?>u=RxKX}Tc#c}-UYT<|0tS^88umYb}sX}#FkNQ)nZPTyl(Nl zZ%GTjcCn0|CliP}LYQ|&@PdX>zx;wiF@wYQG3qi_YoQ_6K6T7GT^30-r5uXO9*=M1 z6i1mfmhOL#q}4CAwzC#L4kzbPSud+|K=u*W$M`;T-!s}~t0dJ%sgV`aFmjgGQyVqI{z#Q_q*mII-6to`xp zJHb}<8~y8pZP{_-%put{k763K>PyU;+yRty))Cu~3VVU|lHB-la-arJ+z-5Qa=_Vc zqt|Vt(_`?)$HB3J+gd7t*P2D@Ub9|{7(1ChKf(l#>uWvVibh0>w0 zr0AklPzoJ^k1A2Cj$W%NK?RC~>vpHE){PA{drkTM{?Pfn_~bFV1T4DX8}QjcOfZt`lp0vK`Q7h!(CKuPSs)>apG^gDYhUVl+0&CX zqicjLLpeQDVhu-U(>3|*^$P;73AV~r`rKKXpDS?7zfWk_{7CsiQh$6BpHnI{uNl22 zx&#ewE02?TjS-L`tPvzy3f}g1G5_#;%!gu_r}0$eAzI}Pbg8DEO(GB`c}~^QXjUb= zs(M;MhsUIA^b$Tg#mPcOY9(Jfe3%SGur)cY)KG!YI=Y<(nys3ANBCF)DknF1{LM+B z8d^I$$US|IdAj3jF>z!*Os3Fl*5usbcg%dhd}gnKdbf$TtRv3@)jU?dpOr%_L>^(; z6+=RcARc;%E;D3!F7O!hTtZuXJ(w}p;kwov=r(F{zMt*G#wlv^N!drsu8&zHiwNwkyLra*hC2gZF`bPA;p-nltYbmU(eo3E+*oY+tKmlz{PkIBlRZyM#$c z5EC{ZUVFk=ot;6gaf}nxaEKb+P*87G&}mlDYF1J2)KKl!P{pZOTsF;nTIC2Uzx{!@ z-7odFG=l2n*U+pU$vN3+^BTn--Rd0R@s#T(j|ayMoTMY@ay>V9kP19R)-{UcZ~!S= z_)M`S*fJfNV9TIdyEb&K*j_8P|1@RyYSmd&@%+0l|E%!7<%;|lHIGt?yfb&BZC8eynC(d&<4{3~ajuTa$9H3TxF3=ufI`AJ~$O+UN=McIBqllnZii zeG8>0e<1B8%nV6=tyyC$s;zSXG?4l$E4J?gTe>5c?W_qNz>0Ga3AYt<0XML>EiHw* zOm*W8k_WKwIPw*S#h?wYj6zL<(0+4K&5Y6TusV!2xgpsXd8ppE*dh7Wr+gq<+|Vi zxp6{8t1YQ^tW~5lElrlnp1>K{Du}hqWCbTI)|?Ed)X}OGWEw{)<(3LA>uzZ@MOST_ zBo%&t3>*?bIB4ynS*Hn~x;B~DRGwMPOHim|OxU$r(sy#s8A3k%qofV8r!v2ngj#N& zD!1SSo(gW88I5ieT>>(Jq}9OE&p#{EBAXj?9=}R8rP9Sc)1!yNsWEBOmi@;4#aCov zkiSQzuGc_qX9Le-s?`zAZb~nn0msIKnc=~}>oT|EeC|_yhxod>W^-`d!0y5VmO~Ga zbkjvS3ibu%^@)BCXBQ}Gk=BznF_2feJct<|SHBI^T3C7TGcuuv$hd-_!fk@>nS#o8 zN9 zZPqb;{~_ih_mK?5qz5UE>H5!!H_i+iVSI)v#R2MsK=T&e?8tSsncu?e&;z`51@TPt zVTY3?1gvfw^*W)HP8vL;)b~Uk2jiY$_-hCh9v@?EY!dUXD3;HZ?-N z-`pO4Ca;;N#(6GhYo`vHQdWtS?S`}^T5v`Y*CJTB{|iv(O@Q|)wQc4$aZO~KLw}M8qe4><7#2RtKD?)&?4kPp6($@Di@Gi)cv$+U9Y~V%kh&eK9K&Bb*>OxS&}km4EgN zZ^Fb=ag~{-y4Gb<;rtYZ*RL@nrK1vf6LEm;U6~{!9J2?=!&$}){{6-82bVZIJyet6 z{QYSc3o%trYB`*evQmBtARla5D(ExV{$qKne`M(WuUBmU=s@dl{~sA_Yx-9LwAJWe z#br0AeTiH=g0sa50U?I#F+ztA5;h98w}HriX8s;a|Dk!kLEJWPB*g`{mygEtiz^AA zmN$BrxL8>im7(A;yzpbNWxnkn!8}Twk-fUMgjqJF)+(?iOcl)_mg5FyGclQcW_af5 zA!lQOu9RN##tjrl0Z^M~Q$tD?;Z^GPRKi6eaO{DtJm0Ty&RnS8C9uAa^2pa{#O!OZWtktUvbRhB{8**E z{WBHYwMYO0wp8UpVPvBb9L!DvmxnmL+{ZC`IFZ-TNrNBohrshdTmg zJb#C{#IX#jsgK>HRPg?A%6vOcmYnvm^?pLiuaqoR(nfMhFJ7y>z6-+iCH7A_Wda;sDV0bC+pFu2Six;&+6TIqI4d+TYYw5F`4+S00M7GO zQ7ey*_r&x4M8KW!t{QP(twRkH}??#$Zyj_Fn_Geh9K3lI+*ct!T{sj)Si0EN?WO z9spKX-ZLlb=-; z0j_X%bs^{P@Pc?suX@rCxE`wH zRLj{^R1X2MEBUS~lXFrkCuL=cT&T zbR7$rC=5Qv&U_Y}1RyB#dgyk$qGF%-PGsVT$A^9E&})3ntLN%?2gMIBrAGULWlBgn zLy-x#G`adm!Is8SevYlL*b3NkLWbvs&k?3hc@qi(uveGpp7Bal@9*}GK=qxIW5>A~ zCYd9x4~kkY;LdYTMVu)Yy!x0M?WaBP;p(Z=>}dkE5(#mP<=3w;W2eMb`Bl_WA<)t< z3H&O$g_C1!{9m0_R>QbZ6Eo-P81nuys>Lze?_ycYpkxf;=fIY5>npak;GZAz{>Xs( zYq$L~*m`wfeL(!9F8`=tODJhO9CUw)wtW|M?JLw`0pwE}&I@xYw2a|$99VcwCK1*1 z<{Bb@52)pLDzLqoL6q?lpLAZ7v{GzEBvISS2MNJw_YjrmFHndn#rBVA9(4n@_XKKx z3buXX`aEL>k$*A*thOXfu-D^UtO8jX6?hZk94Ov?uya0JX7RT-u{_Lj5;jU&KbX6_ zZT4eL`$}rs{wAS?+)OFOtVX(I8{v5%ULoW`Z6xgy$$+1$Sb9v2Prv@X;NmKcU zYvb>vgh_#=T6ES(R+A)t$)lD*6Dij5{Tzx+GpSGI&;BFtGskv4N(X8U)kqXsUBj5I zVL!j9@>4H31mi%AgKBCsYNCtxGTtXBe(-d1(u*o8!}8lNKVUgNfSl&2QaH@Jz6G{Q zsr?by>VAnIE|qF4iY*;gEf-6JLlUkjrZ<Go;7A5O^xhjy{>k>c+p-KrOgsP_CkMFaO5=10iu-irR&3ohr9-wHaz+6o+Dw09( zxs-CFYQ#RR0FnwRFV8Nz43p&q4?~SFdlLToLo$K+%n)W0NvzWhiQ&~3JqbNkgK>4t zWgEO>FUMPk!)jp6{K%t171iPIF&j=IoBjre#k%bL&cVJq2Hv&DkitX_^E;`#-c>GM|XC^XOnVOaSP0kV!UWrpYwruLmb1PIy zKQ%Ss)u%r`#?JgQ7VRMv+=uuON#eY@CeTCGlQ7FZN(kltae|4BeUtC|U@MC4We>T5 zZ&B1ouw)ElY4EAHf9E*w_R#C~M14NK;yT&4)y{U$d(uZw2y;v?IPc-2P{V>dBzdUI zsYl{?%n)9NG&4$r|4Aq_Ck;69bE%F!A2%|W%IN`#bT~wH;w{D#4(2RFY7n#LZ!?sX zJlkKBWBU=EsuVwy@`+k0g(%ZKf*IbDPVZCEc0QAmzZ|O#*ZVETX3$67Y z2wV_sxv5;re|(Too!L7C9UcEHV0$~q)(=Id>Rhryn6*M!dN=^AwH4T25ZTnAMa~}& z8wHOm^-$-7oxc|Vpo`_&DzXEED7qFZS^z82e(V@jJHPymV5#F}?e6ltGCUG+P+^8tzpY7shsKCV0#^k{CB{XH8mFp22o%rGTmFR6l@aC=rvD(@%uctg|B_MkzRjxg-NB1QLTc5{#1dG2|3SI&^4h#$2%`cSe!ste z+#fa-oa%wm=_&S?3RsRkz_LClV0%=k%dPx~X$SmI{gEtrZ1}E!jCkdpT!ZZu%Fo_l zDL#UNl}5!#pc-|gtWiU|G5Y#Xf-OUlS%Qd8)GR|YIha9@UI*P%$y??T_mx_nKR&0} zxPM$Kc)L^}a@Lg`Th_Q;G+l8Y#tD^2FB(ZAaMWuaWA-PWJNEr^hHUdVcGW%gs=bY= zp(hx()0j>SpfffBFeIPV4m`;7pApy3eJ>nbDd-mf*LiS&t?5Njtt~kZF`=c=tF4G% z!=X$pse*enoaFv75`j(i*&DExduXqI{o1zx03ZNKL_t)GV)7eQ!mPE+I>ih{?g@b2 z23tb6QjpaZO(og~Xvyd8^>C4^V$Mio$r!+L@*#F-vdYo7+f&yA=R#w*amWjayM?U+)gNgQc#&geJZ!sfB)xlY(=p>;c-+W82@e37;@11d*E^)ftz_dPqa&!a*Z4ifZIpFA6?g`?N;pfE?Y9+*6LG5)O zGOts~Q9eQG^&3p-aV(fAj9V!QMLzE_&V>rS%BkgX<)i`q3D}sk&BkDJg6%QQ>n_gm zHtHg44kB+2VJX6#S{|nqK8GUz`C<09y8C}x=KtXLY(G^R|Fb!_RA`%j;N~mLKRu5B z@8{SG*qUF76LM4k0v$Rd-v-{dvGvfQjnNpA~GQU!oKJ5(M3b&JsQSSg<3Q zA4~vSYo7Zs2Nz0>@du3@6Y-%=6^TtI0{G?uosrvEPGwMWZOIv3(e7hgzlYWE7rzN? z^ESbDRr1aF0A)t2Kj@L*M-Ij>nWM)+5eF|_9QF3p7Vd9j>ERG6F=Zb0YrvL&vtowP zj`pJyji4F{qY$%jI5z?G_GJjhS!+JL9DW40$ERrg@K%9s)J4;#d6c8_XeFQ4H;iHkvfsRVwVJQm`gyhv zDrQW|&n%_~#GpligHqu*cvcyfs%vrcxP?C4%HWpUdvbx^a$OWGDp|}wM1f$$fhiHx z0~fDL^6v;DH-luZn9?+JP*2f$@fOA8Fv@yDa*4%Jm;-oEk>!zMm@wgijq8&zVh)5E zszV1_8qIBO;cX&?<-rG%tGn{%ohqY3CFp`?Na~v9{;+vRUtujn7-gH7@7cxfToyBt z1S;-B zdlTb{A*mBPN5%HTIIy#)`pG53d{sa4)mksrQ>~ZlmR!#ZQTH|{=8-jrP_iFjT2JG= z+7jqJ>YZGNEsNRHm70W6YOUIH_Fn=NBP+O%mDpp{g98G$<-zZP!&98o?8#FIX$I+= zhp{Td)y1V4iLu}ENUB`&9+0bHCK^M*WUbg?ar)&mA7@=vrjUo{gpf$%BOYIM0r|(C zOEH%^-bHovwSeucV`ABip{U1Ei6*7Qkq@rFwEQI49;=*t39G&pRU+q;6Y$=o1-m#^ z_uk2=O!oGco0yKIQ7|50(Hz9~TozYHhoYSFIVomSH0JWm$OyDN&itQCd7of=c!0{Q zH(0RJVjwl9CxDG@$gB0cO?^y19;xJ<;m?C8LE_h^$3sw3iGtQ@D&b_WDvxg zPxlzT+#-r;M{+BhR-fd~wu~=vbF5W9Eupq$@b#DIIA5Wy{}mnkOVsth-6*zy4{SYw z^wx+)9;E-tf7C!w9TyIyWOTzf`BFXCWsty!0v{Zr@b;LmM5CB}lwSVuhgNKx`j?Uu zO>m-Fl!PKjzr?Bsw@vL1O4@xaIbqDD9bk{@D1(j9am@TAo-8?DSJIz2n336PKW~kS zDa|`pR*_GouECbywPD=FO5|_Shkk7+a?a6!%~i?wIl(D*aD)S#tNbf9Uo7X0V0nVB zcs(9oQs+7mx9+8HhW{mC+lcfD*w&&El;aLg<|n-pSIk~i7Ai6**wk!6q%)ee!l&8xFY`}0Q;%W5Nw;#uoyYf zg*qR1FcY_N%p6NH6L!3O3j-g2hXZhNc;IK zl#@derkl5u%EX9yhT_o6zu+;s5OvL0x#da$I|{JmvtAUAw<0dMe_SVD z^L|B6lY9PI59OyXWMYCj(pB9>J!)KoE%T*)u&wJcDF^iHVD@%iZW47fiK?Z-krmh~ zs3q7|HA8CLR+32p+lhfRu(2-ZLtOf=c$Dd3L6B!yvEomH6&v5X4k_)PA^Y$lW-JFw znlANz32J_5z3S5(JE)E%F84gfoYvtp&yRwkLfP5ISbP9;ZVHQuG&V=afnAn$Qj>}P z_(H^RuFgNkJm}KV_&s#@KEuZNoaDtaBzD0W#w85_ug-CDekzj_{BAbFEmd2pwFGvC z$a6xIeML0O?l~H>b3`WeeiCf?-7=A(CX?73O(EF-c|6s>T?3_M~4EoS!V!qAr~`NM%AXhA_8-S;7!`H z|L_^-pDP|e<}1sTgv1)iwLE2K#2uSpoAX?eZ!5Mmj$*kVs@;U!YUs}mc(+x||EAZU z!S)ZV))L5lVEjWWwgR?)L&yCBZT)`*Y-`5fP>uH?m)6i@j_n!iBmRtH%Lkn|*pM;H z@9>Wr+z@OPv|bNf`3reE@EOnFbM{$1JXsQhuAY|%J1D(;_9p;ax*z`(Yzeo_!7WAa zV%Z8{F=Ye$o2sTKA6XYF?@7(Ps_-lxBTlN&REjgvA zcVsezF515dY$ZJUREn`|T^(QtX9BlWLH%>aM=ZgX1zT9Kzz5shHzU6pY+1*)8NQE| z2wk2v)Z#8qW+#B|zI+b@GiBDA4|UFm*Sf?~|UVlswaDG!{n2B&9|;=zML zA}_i2@B7=x&~fOEM1_xRF*K$d^CfCJ&f~(yyvRRdl}VF z=05%yYz3F(-YEOc?>#(3^VtglTdJ9PJE206FHR&ZmS#W%ECL7NK^Vs0C;}}ZLdtyf zfYlAm43A(wmc*>>Vsms9U1nyx>Px&@&ilbcqLnS9;x=PZec1lsMOy?3Og+K zbHHmx9q+#jwghLt+*0=(>*F(GV6?~_>BIwEH3+sn30Y;tgqTcGIlff!FPyw5np1}K*sLTLz9WmIN4kj^aWw4nmNT@KQo_3+4pLmbq zb;!p53AH}~+mjPiSSQ;V#C*_|Fn(<9dB@bNu}sl~{q@qDgyF&B`R7=Hb%5nysk*!K z?htsND(ZtMY6BlBwvAv)pmteLpd3+f``-k6|4sY)8Eij;?eCXk>w)cx^H&dS|Aw0J zm!E>I7!s(^BtGzDhM0F^Hg7QI4>bOhOS#!gFy1eLt(sZn1N7oTfzjo`77DMvLoUuR z#sL0^=21$qRb_pe+Kpn%+}E|p7ZQ?O)$Smx-NjPM1h(3cdX+SP;p{oX4`pD*oH*rv z$oFU-B7<1Y?6baSyNztzmC{IMD}btb2QBAIG>pHZ@f*RmS1rk4gv0#3%OmXJRLU+0 z)Oso#2Q+*zi?AuDT~Ggr~kD>*2tYeRppgwQs*e zDLEj9M+GOTV4G!pyn6xj==klN1|-~yV#sY_|7Ns{2S&YS6VpS(0=Cn(gS8Lu)&5uo@r6f}2LSRFS&TT~1DLyEtjYP-=qAk0vp> zjm)w1eG{rrzC$sQLCub#7SYj&>S$^{*qSogpum={*D*N`zaDPm3Tl4@wp3~fwQL>R zLDev&p7CNliK)y0F4{DYqHzz^NXl=X>+yvOt-TGl0y8}Rbg(@=#O%-j=3=&(+~o%c zRQ*uu?3b4+|56l8HGx3KU%w}aBF~8)Lf`2bE}9)oCexz+F2rKkVvaP+QHf%EA)>6W z{8P0hQwbw;03cAqd!Y&+ZoeDHf|ka7FfL$pR;pct(T~AaCQW>>z3NJhY2N$!{9%r0 z!+wa3&@kHJArxZ|mCEWVh3uOITh*sMX`6M|nFq?LB9{9(J5X?&E1~ENARBbBY$S0o z?wMot&aMs66x?#6QUR?@CQyjxzH;aJ{M%SZ{q;-C#av_^8@ItW7ji+jhOKEA-kVne`ovOkV7J&CoYW$=6xZ1-gX zm_^QRz?Rd*RBZYGO(?R8;>dsh!!_8_c#ZYEdEGIYz@LB0Szbn|b%)em8{a>{8 z|BH_Omwys$KOR)w46pt(uhbw;4Fct+&#(2L0Nxu)vE?vU4Q_p~y*S)J;q}u$JlN8h zh|LFELhX9w3u#nsS)X_@`~|WJ4XEdUQ>rRzz#}FT5*Wq`ekWkjb}@$F%r^(HXJ-Oy zmxThRObt0Fg0d4p+5QT3_e)f*-v+kKvE7}X0k(Ez5KqYP=i_B$#izZDuDsF`1QJFN z93KG9wuJW8oL`?~E3U{|0L|b%Y-k!*7~ZFA*n0IG*lOXbw<}=F%rJiffJ;8`na4yI zPHvtI_>Rwjl{K`#{SJ#-7)_fl%b&s4H;MYx@|RTEzxR78wk*5T)FP-vHB?*&Glqu! z$q7~3sz;+E_I2N?Moo_J+^ME26id_s2aKCLs66@(c^VHzz(^{Ycce@GL z>MFPP25gmCQQ5GOk0nri^axn%KyrVtR1|;=FcmE*X!GcS3W$PUrLu00P07HsWTsI_ z459t%4Y0cj(6EJnbA9tuFa66##^wr9#jJ>RtV>@%K|Ya|&{-N9owsO2#WE;8TwStu zClxfMw6bImC%^ClFUB%|Y3<@cl)1|SL%wThNMj|Fo&zMi|FOHt!w*o3CDCwWsB1phYMx@Nz?LE6G?roxv~o4R9a{X)yjEaau|5t(_QAGo7*d9c z;m8#y2G+41izTp|%i(HoPXYVSg6*Zi6{F=PEs4jC=X!4)qbU~)Nn5-C7SeGXZ>-^% zu*ze>bH#}_=@V3JRiYA0z)09LCoE~mwY`P?TpsV;m{O4~3ytre0Uc#7$aS#~Ntm~a z(3RWqHQ0)*sdA~$H#bG`Te33}$~x<$u{Ap{z|Q9hznlF^@~#P`GD)eNdkILK;9)$@ z@!2k}Hr7SqTMuN=2@Rs;KEV0v8qUvDT~?~Q%;!|s1}8f>DR3^TA+e2Tqc6Q~C`n#y4|lEHi+ zh4DZf&CwYg@9yH@{6uo&`5cuAJ70oks5`vecJ3S}K&agB?qcro6D+%fa{iVQ4{%bb z;Nn!($o@I7 zXK?oBTlm%LcKu6=tsjc)E4D|tI9f;H^%E3g|9-`mx`onbIOtG0L7e!e+Q%UY2N5!R z+&jd<+&e6~{m2`4L>Xn+FLPxHuBzP;2Wu(yqcbPEPt;~Q0@E;xFiW+TZ8iD@R_uFN z3jALz$Ah@cP67uTz`>@cWHFSHs>lH@FV%qbl6i?75YhdV4#f2ej%UU(8oGlew;$zL zKg#YMRNSvnF=+gzO8)qYqzX&ERm+z7q(5p(u?(PSX;^#p8dse)PYLw~z8t_3tR*Lm zs<9VF$I!&XJz#qim!&dh4C6PI`;qO^1E@vrW5tZ3p+}I72GRNcF)rFg;BZxrjTAw; z;>vFiqKxqX_LbfN$j12WAI*%V=Dcp~?9YsBIPePGza%}t2HdyM1wQL!R9FS;% zn%RGyXY1$Q-d;8gKWsT9+sN%?*ffETVYojBjeMVtIjFar|Nf8v#()3zXZhNHUwuA` zx^~kVQ56RKR@OFagKkZ*EiX5LX*5th|4P9&=1AC1WVL4i@4Lwu*V29_)IM%shWjmF4DA#MkG2M8tBeZ;_R-#r2HhfMTW4~5H?z``hcL%T(axkU4Qq%bA zcn`hvLv_A+{-`)JOq~${Jb&!l5^B!(4{^4=j*D6YOMMQS{Yf+;gDAKUa8#_|Y86+mgaP(gR-ga4P`TlikT4;scIw%ztzJxuT|aJn1n4C zqx`!#2)ZoyQ;Q~0O^o0uS3;M-Ezt-n7g_EJ99!|Z$4C+>qs7o)_H|C6Zer)%9HxRv zWFvzZyYHg@!v~zSR&jCYO?DAn`TV3=7@MRKcuR(>pIxYEtj-!{2OkL7&WB@|a|W?J zy?~1yZj-0VvrqDQEPd6Bw&3xT_xP;t%H;Ik{IV$bKG^2_6R3ohD{?E40>PH~wS-%i z{83;V|E${n3G~Qw9UP2dg<*4~)8p=;dcn%or#VYOOmS z*!m!=jH9@{{@YMN&rl{RrvT2eW-et~ySK)VK8-i&{DuvKu&8BL`K zaGP$ni}!PaBWGphGaTez9pUnD6~$MNQHVzrU}*Qn!PZwmY5G$W^B>msRk@PPmuy78 z@<5ZW!+oggVN{0FG6>^{zHBhEXS_6*PfZi6+qv;DnHxH!#CysW2?R8+SiGzt(SkCB}(*KHF>@M=|T`cQ= zlWkjd16T=vh0W+4Y?}A5X5B-J&f0`>?MrEGs~;V+AFD=C8bg2S3QSllSsIoG(x|_A zh0|&g*d=stDeykrR)Z7{-r0_}fxQi&Rm0Bg1WHdHVZkv_wn9Gv=O2Ugr+((OS9JQ3 zweBJB1W<~HvET$S6APj8`~i+C3}0IXPS$~wO*PQI-kv>R?*Q010;(H0pPobK$z#bw zt}?tidSAen&d7A8ZrV|-xdyfj)?N)u9oxDUMBV8}Nv9imKUN(b>kMHGhNZEL4I$XC zfyBH9!WwG#`>_&?U@a8IN+2xDE#1O~ zVS&(EXYR703lLX=LDU05tVeWgMGR~PqS%V4TC^P>a77I@QPFjj!jbE6QUc?uZlI$Z zqSE@n&ErrDX<`agb>jkUi^&99&z|8dy9jKo0h?<|!KHcH;g*80vt8hX?GR`;aWpk0 zYI}KbP!!g@ zYryUbu-yhWn!suet?$1V-Bjeg{I}8W5mFa@$qiH5kcao^u3C|2lIUe)diy&-^<1*LHMwjK59v47vTCwZTuhCgM z>Y}E(s5xnIqNXY>p}!m4r#*ns$_YC*{>(lg{a_DRUBN}Mgx%3GG@g8eLNbNC9Yfi2 zkaOcGJb8l7_!xTi8nCyc`jD(^*IVzdn&2VK?e3sgEMeu%8!Qbyz?2iilx1VqjbT2W z5rEsBodec+oR3v`DgyTDF|K(2xn6GT{w6Lv4IGu0Q5$=Mseyz*Uo)1L$%)0GLDXl* zu-Pnl_waq-i2eM~+m=Ih-SIsdX;mxO8J$3J=#hX=NlQxDJq?W--@nAh^sFeSIM@e{ zd7T`H(#ZY60ae%oHTiLNgtK}Xwbw7D*6)m+z^oC&q~>7CNud1XTO7_Wh-U=$4^??8 zM*ncXcK3mOPTri#@@jnz$Mp)9zI}?xWD>K6jb+_MQIDbGq)>>bK_!@>wgfhY*|HJf zxa4~Tw?a4x8YY$Wl(a%5j$*(?Ef_~xPoeSnIo8Ieab9i$Tf4yCk(9ENJl9QLzb7gj z``{GV+Q)gmrhEWWUt`%C7Bjh-Py&;B3dKjyaJayG%RX>;=Kbv{uy+jXA1f$6?yA?F z4V)Jn$d5dgy!N?hT+Fr>?F_P+hiJckkCS{+J>&SCk9>oyp2AYV#d08qVAz|8001BWNkl8`;VMxF>`Xy>^ z2>G7@TdIo$G66Bkxw!$z8y)pO_ev?YKL%T0^-$aKG1w9y8CJ@hbVtCp82i_QEsv2; zt~^$RTGdoOAHmjFYq^x;$=T4K0bAy?5)|vkJ!yXrZ23D?&z8=}U!bG?6`L`t_Ftl8 z{0)_OAL=6pnokp0eKmrO@$a!Z`4X+km#9v>mO}K6vA5`ac#HKn&$0RP8x+$~ESX;+ zZ-0SW;vTB*UDWM6XqkOzgucRR_$#bO?_!k(R>nQlJRq-H_ffa{ylrNvbRXzGTo2zz zJ=!OLR<$+E+d6W?gJ?bb4x8`aU~}vZ*2i9BW$YC?W3SL2dydZNbF6)Mj*a)vvG(#i z)SrwXo3JnwzK^OI_|;%bU@Tkx5?)<(f+*Sj$Qk#Mb3>?&#If@15jHVRX2i0%0wk$qT(0=ckTWV zntgpJhwp=RZuy-I@2*)&)g-7%IBUcZF!jNf_X##}Q1-yK9o9Xt?Z1ZG+hEHYukF5m zY=k1%j_OzsM+9C8u>#1JhGH~;QY3(CD1>^TAFaM1+Fq;o1yBoyP>n=YsBct5Iid+{ zQjJ_O9Bi5{whbHGnuCpqj`ffspj+z;A%E|l`a3;}DpgfolYQINOl$=WtltY^JERK? zw?h%sBbt0pK+v+qO_mCosyj+hHbmXMQJbS^>oyt@3zdkCqV8Zxw=ie06v_ZvPrsF% z=k?dGvG(RQ*51FB^Vb=FkJi)&tWJEu=9^boefkvT!3?slBL*?ct|O3DbX*iI6D5;? ztKilLTOabTOUZl+Y@-Is3~@IMloK(u9t~stho{(h{S0gGUt(=)9Bo4N#H0X9XLJ;+ z@84nl&0B1~euJe%3JaEvCBqPvwPe~TYC2j}TOU8f>WAm3PdrCs{5e`<&*ggIHN*FL z&8)qBhW7JsP<=dv{6In+yO-lOatR0dR1C8T2f2|Uw14;>n{QuZ`~6#4ZoGLV%Jm*8z^NG=zRMaJ8z$3>-`IC zet3bk(HHXftCO#=GWiN?6K}Bd;T_hW|A5BB5#*B&vQ`8+JuE2&EVV<`ecc_#cKk86 zVvn$5qy;pYJH2YUSl1HRFjDeevVAQ>`DKqxA4GvZ(owskma!{SO@6dSv4z>61(0unne%^fZ0iCDcqmUR7P+W|-$eStTtpQ}M4Cb8- zvV)IM`R=*YU~a#8i`MHm5{}Ph{oQL+-@lgcVJ>Xp(POZ#GGUfbJFB^vj@X!qI^vdH zd+-g`e|U|pHy^P6epI%l^7ai{FJEKr#T%@@e2di=Z%}>t9Hr;aFgrAeF~bt5ZMy@g zX>sI2mH>PuF^IC35p|hnSFMn0eBFp-P}MRh8w1GcX=M3#(Krb0wP*?rPub0xgD4I> zLFegfY`h%9`s;D5ydJ~K+i|SEn~>L?SEE>c@d2Ih-=aSJ9kTWimb5godIs5O26Mp# zrkUUD45RVzIksMmW9!WnHr`BP?d>EwZ^qGnJtoVQw-fTZ{_HJk-@HH}F@kI~iP@kd zp~%xAN6IASQV-Di_9fO|eZbo54_M)Odh-FTw;#}YKZ@r2QMBKUqVxT0v>twsV)B82 z@m#>cV$csXST%fyAQKCn{(;7DP1>miKD%`yiTT_#ariK1jhP|||P2k#2#eM*u2rT05pKh`7t*wsSP zHbZ?_5A|bHXLzfIVkCr;ZHmh=p@*TH%T5BUky$pkJ};x>vYUBbI7X$`f6iGmhIDI5h=p%u$PEgZfTvivEq z4GYxzs;v*UR5YpB*6-cJMkI-CrscZZ zK^?0BOhUCM>^BU3wro*?b9xlB2@4Zx3zJ@(PFY~%`>dzDoQ}!0Oqiugo3l+6Z0owQ zYz&WeEtx_ioslISd>PKm<{t}whOcv`g=J10n3nv^^GYbqTPBt*0}Hl}Mb|_&Dg<+uX5%UTp!hBwC@6jCwShphKE3j;CC z55_P%6vM(0*O$gpB7sHQ!lI>N*^Ee^u2?1*Qk)GKSn4;Bqe4c|pt2QpL15iTkDzU& z&~XM(v(l1}$#8E1WYJC{r#YxuDYP7ZCM|W1nU~AS1s)?gUQSw+*qW0OC9mYDzm>dO zGbt)C;a3z}hPWFpvW6}95>CGGd{3oRn@OfHn@q|1Ux=qbvnlq0B`1z0D<+dRQomNS zkkbqSTY~Al6~nxnz?_@FY&5Tk5?Zz=_*qDl%n2XvdI4QIe!)S(M zXa`)h12MEiaZwWU0SCEg5(Rq@b9zE*oG!*P0>bmUjfJp@4->-`sGS79c-xl}cd^jdxNxhmn!GaDPilskY)CxZz)jY%u5 z*69pj-Wf#E8bl$Q!g3@b=X@a)!*sue*+@*~-5N>Em`O}qNlcgtj9Uqe*$I4b)ayAr zjYT7cg-Bdnl@|hzD7J-Q{93L3IjB{N?Z>L^KL@s+lKUBKe-qq(2HSr_F0K!Kzg;yY zVE$h1GuZw%JpJ{5{TXakj;(@P=HT9uTDBdjWlP2O3)F)DD~fL|7C<2$!dxtf$#?{# z@hINMBbdrqm`a+MOmJyqCK1Cz!UYGy1t*HUMy2=;*6n*(HNHSI@ITnl?qJ6XpdGo3 zx~X8Z=xSJwMX~6HG4F)1;D(Wnhmo}dQf?@3GW0ltx~-vZM^H0DsA&PLSXAL6sD-_- zScY~RVHEU!EJvwo_9Mq-_zue9yOIyv(E?c2f>?0@zReekIzE?NC1sf&pp! z!65d6VQdr7LJ^eug93Fjm^U36T;_~83OY-PBvFc{u@p&R!A=S=&BaadIJDe|gbVVkqA~oAv6O4m3QkJDB2OsMf1mD1yaML_W_60SQ&L41o_G%RZM>f$VLn-MQvm?D!GoRQ}d>SIn%+6Wl1Z*zefpW2zA>`92}K6nCYSW3HHMRcsYnP1U!=@NYTx39Q%& zwCp%of49c-s}Y_ZQ7B7c9i>1Ng&m1^F*%50au|ga+aPl3K@?I0;ylg2Z^wtwcGFT5 znJR8kQ`djaa7S+xf^^C2=?j$cciy7L#yX z=2r>?nN*%r@_Isd1h}alQvt0zEVY%CCONFJAvrg5dJNN=gBjfgU(2>=G0BHtq8b}k zC3vVnCLe#8nQ6qrZ8bAWu1%B7?z@H-2~l9 zgWu)I@mke0*a#-E(&u19ON;tG-5152mcp!_mgRgjC2+~5dOw8^K@*ck91HFM7Ok|b zpKi+Ke$@!XtoO=NNizW#6MZ(u`)y2wTuepcn2jpv&6>rCK|kp=uCU z17$miq8&g!tn$J4k^$_x{n#+>3P2Ow7Ob!uSSM}FXI#u?986_w%%s^Y6dtCroOVIg zb35O-1u1AAdiv&PmZAbe)f>q||GVHk>WjUjJq7rXJ?qfUBhmB|- zsJea%Tz~0({_U35kB$C&*a+UoRy2h5a0s>jK2)>_T2!v%F)(LyE|tPuDvkMM8jFbm zOrAQcMQ$y7ZsrtdjEwH6&lH}Na0&KM)+L55t=WT~V zXoZ#GR9TB)DH6cE8Ny=1!l)6!sHuyy?WAL2#<9U|rD6$7nuy2+32;WUxFmAb-nT%-O*d<}yiH|5PN3xlmNXDOqc@ z7}5lUXCfM=3V{L{Nog zBUG~alM__fMQzs&Z`+w8tlXMqeVU0@#Fo~H*l30=v_d8tArt($qq$g#I`V!qXrLC* z<@fxXcG!~7ao_4uLsV<#6H`qVW!ZI6^IA3LqUtywHGYPm-Z5^c3=opOPNQTr~7n#0ChK|`lD`3#Dj#kvyVA3$>pt^HwILGO%ki@x)Nn<0u*laPp0gz*HI+BQ^+rgiC%#9DGB}@pMrSxM=k| zSdXUAiKf&5*GQwC`3CjOQ&IG0+(FF52QZr$#9VSf?tP1KPUgjBqKK11%q`x$V`Be~ zjlFOh#XbX*AsvN>k1*$^Fz+a(cFxUUDxSeaB7^DJAZFYQmPa08Hjxq2DJrJ9C|!qR zsDxwUOkOdPN=c760_8;`1vcib5)j38IBd({z8Y|3pPI~Jy=$WMMHHP-3Z?rtvUe>k zhvLYY8Brp$iD4`cJi_e22xe15Sd0y#7#~3?^$@xEFedFd-iCFVw4^CkE1bYqG=r7? z7;61AkxF9ORjTS_Vi?nL)u^(vO?%B>KjC>S>VUbdC365xV*oUos)RBqh0@|6oDZd> zR8BUeRN2{JOiCy%hq=EQ0a|{(8cd_omqhu#3h^Z%GIy0Zt;I+R`A8B3Ou{J@*riAU z%UVj73=?MK?+LNRKpf@%xB}2{3gu7|R9o|b81l@Ajqtl^`lP^>Vase>r?gN^K$sB` z@_BBD0Bb_l%iP-A%~x;z&-^qLnR&MVM6T_BxnlcUpq798?|@pa^E23f2HSt3dDQ0| zTX7VmLnx`2sjeTHNBy~SY;Wq=D#v7%U#pyv71-WEOTUk%8xbXO&ec)+<^lE=XVGg` zandZ|Vy%L!wFXcmEL7AxNmNsetc@c*G@eT9xgQ?h$l%jj79W&l^E zta3x`G=X)R!mNnN42@>6(ZXddhvS7QtiJjVMTQRAI+nE%iaK+fLuiKyr~z!~L9FRP zbhP{8Buocr0a`=l?yea3B#)Q*yc?0b*b3j3+}_^;wglf5D}Z|Bj^zHfjIiXJE{6J0 z$t1A*;T5pbkmGW--p1AXia2g!bxlh9ptFWvsgC`{EXr?RU~Yur$YB%-pjre~L*)=x zzkPzenQ5FCia?FWXj7T6(1?nrI5h2HDVUWN^p=b0JbQ`qzzE9e6pEICvZ+*ChB&vh zkY@}P74s-DQTiG4D267}Sc;I|3P^kj-I?!ON z;gasX>=RpSK)Zp{?2_b<7Ka{)8rw`#6-%O+NTL4dYiy5xK)0Be+R0ew-?V^E2Uz7X z;_+{bBXF-##AP{$wTE9zsAwr$XypJ&+~L zvI*Q0T%(SFEtfw03ed8yuLryJprLB~(sejuhH$x~(-@L&7 zd>LqN0V}&eYZK^fit!EBcYwwUQ11ZE4!YR_THn7wK269OLCGBym68s-RAkp*y~Dx6 zB2KDh^mxys;SWuI*0(^zp{tb@pw$Fwb)Zy1WndU3Hz9qD{fWTNbHvbe=3etWE9Y&R zQ1Nw4-V?Rl>w_#$L=!Xi7xo*1Et`ZyhaII*M&hVzNz{!LYI;)Oa5>B{TuWM^-$FTH zgYee~GF&);b|i^%z(Pf12yhbRtYZLO9iA?n|lP5?~c4;fRZ}oh^8FatDt&R3M6q{KyzhdlE5VmdKsUf``MBl! zUHKh9Ls;eaSA)0OXR!UZnoE5K+fM-G&zU;?r{43`%-=7J__wRJzGCYyf2`R0`{paQ zx0n3vXY(ippugtd|8~Vzfvs{(CJ0`GZR8GCBPuMJ?#|1RdsuR!Xnyw?=Y^bdm1Ow^ zDYtM0DQ9!(mDTV|a$K-f$`-n{Ih3C!F|B=p`S4$`q*}$B~ru5ZB7pCJv@YQG1XPt$80+V#dUpxTTRnY|l)3Fw1(IUEoxe;<#XG3cr*I zkJ;%Nu(^lhY!S6@pGl2LDsjvyW$5;8uoXw-h$^>3xb;Jk{pCksOBZH_8S4=&=wUGt z+8KWhw5!1JzH&bAviu6qnJUYnO0(RQXSrPKV0&@`#laC|BOD}KC>aSC;7Z`cjYl< zA7zbFzl4dr=k=>Doj-SRF*A>iktY)RSdQ9a=2H#osPsj}p;&+|Vu`^NO{RQsYeigv zUNHqSIbe1r1eXdj8}o=6lIw%j&C&;2wIp!ycb@{=Rm~QYErJ_?jh`cM5^A{QHn9;J z#Z_70#uDh1TxCLGgznNBS~_#I4N+|C5te@9dkUJl?w@N^L9ZLj5Ak!Jb2DM|Hb4n@ zS*-0!*jDPIWV z*aePQI_wze()HIX_e4l-t>R#I5v2!DF&VM2EIEV;6w@Qv`!FH!D-OR>u7>xz%Ug~2 zgELhc>2M#|+r=&olZHmbh>FLIPR%r6%Ljre2P0^5LVzu7T`zfFJ?r5@FuCD+W8Ikc~>eg<8NyI~2oeI3X%6jkFk=JZ(D2 z4nDxf#H7HvlnG)vmn&7LRO--P+a1zE@&w(JZJg|Oko)jLjH0pzUBq1pdCq_H1Z$O? zD))4|G!ttjOW`}O9F>&XI+J?_ou6CZJd<)(6)T0NnL;(>$o_DjXxdcQ69SeE?q@J2 zY7>o|3Yv>N!;u39@&QX!>8h3xrMF|!PH`XEXxzwqFZ;on zDgz|$wa&;=Ihsj6%N(Q}tEQN`MAmw&eFR$JbX-Z>y@}VB8lMxFzV`Zd7+~H$rSJ zloGQn7nmS3001BWNklARwF(Y`eI`DY`hu`Nav&FHUiO*#ir(_Xu)V2e{a4qB;2t*&!QC zu@IILVKkl%7qCG6(;~#Z;}IIh8OfM<#T8G3TjWk6_;Mt z`z6@2Op>qI5^ViCvf>i#<=7HzeW;~k%aTDI8exTlnC-tW&b7N^Z&gVag7xVEz)~Ot zNNxw~UwQ*j4nn&;ha8-CPtdDY(ERp$84MF_X`Zq@w}i`m!s|J3)&+L=RQVe2Z}$}4 zqkUZY>y>?EKRL%ysfMM8PsQ|RIi5o8$x~H|V|P~#5-)nVBpeWs1#Ve8lQk4?)iLF< zTUo=-vsd82nqkH?`KgCZR09!F0_!XV6w;(5kgrNIjJ6X}DpMoE!80M(%PWmqsC$ih zrUcO&sO9UQg6(a%C6EcAda7+ZY+Nh11Q;J!xLyJu-{WW42%J6uc63z-wd2)9twkd! zhl0}hT5_+W1S6Jx^5E!amJEgF?*(Q(_~rI-JE-J}5=b*7%ei)4rZLfCFpSy00CG{9 zjPYDMVD7P>BQ9zojj_VowOT9t%)5W-&nGQ zlQDkZWereXqeorz7W2ptJiRqH*B#~6NT+}PM-naI_At_pR5-W)(ca(hF zhZO`s5W?@Qz1P;Q0;Df-Fu8YfEXwWc?|+ok_af8Dso2I$6e3ZXtl%~?xF4?zIxsUh z2|}fp6C$jQUNQ_UMGf%yr2!OUmGz|&ALXboP)H|c`JGag4ZyY*rBRehLFVfg{VYcO z1ajYei__YwoXajw53qmu7RU8toZ&*wb|;M!9M_L<(m2Ms^zlAL1IIXdw}HZwe`C~g z@T@l?Eri$`xqiNf3mi+Y=z8N=de`!t$@8Z=kDkfjnX|n&!DPTG4kxCu$Tm6#>-f`H zcl%MZv!LVjijkD8@G!Z~;0t#l8(#>>kQN5{rcSI?q9-}hb zRBprke5JM$UilosbS08)2BDQvAymiuQS3>I(o4v$#RnxsMW*`Oquwu|`~hd=Td=(; z6yJjFwFXOnmO6Xg=lmxqwl(h#J{G?O)*5I#$M@dH9>w1O;y+Qb-SE4`XlT>z!gBl$ z*!tuz-R_5t#p?~Q-|qkQROD6bp1^H8*s`~5&FDha=n)_)u?NZ?=NEVq{1Oz0y3Di9?25y5Q_xHjf2LkxxvrbmMwu5SZSya4!{A<#;X+CuC4voc}sB<*dp+NxpKn1@K!Imz~G}lrs zf>i%q0uce0>ga}{LMyjQF{NtS3Jtazq&WT-uqCuTX_GJse2FoWDwnzJR@HT;*sjX74sp~d7M%K3Ky4}u^wW3@`=W^RW zQ{UF>)j6tt+Btd9y04$t z2l;yrCSaHW@$L-{UygvihiR@xNG*j8QQDWn5#(brxJjbk?!erFOY_cDy)d2oB`PYQd7zAOF=TA-xa^KbE z97@IWSWRFZ9Ehtk4YZ0*TK$&ebcZLbGv(Np`rTr$1A-ZicbGlGx_=tQsqoZeaUV3( zq6ySUI*X0*36(KYKa=Kr1ojhI7j7f}dhx`pMou_#O=aTo>kxGx8L; zIFQs__UGj?bdO`=O#Ao3O9XlL{6Nx@H=q6>j+sS0*A@CL5H zK`L(5R?1~_bUxiYO5m66iQ-+TBn*_2aY@W*u4eBQz!Pe@Pg=lL=S3SY zY0vk7ix$`xVurL!k-AV`EY{Ca=PV1aeI%KW(8x=lOMywvg|hQbs2Uw(a%dQ{G#GN( zddCo`r6Ckukyiz33APGunbzHG^+V$*^L?Lks81_Ycjw80odDD;84Fnor-O+Z@6yl!3$!3A9BHbKwp6+QRni0CIDL- zW%diEni&A122uhN;g#k{gj<5G3I)9FV9VQleS7HT=#fyx(7>gZuZ*KK#9ars`Z*1= z8o>4X(kP0bL3q_5%aQG|bg=yqfle<=-_|hMzTUj8*HN!8N2;Bw-uL=Z45(;Abxpi) ztff9ff39AS4~={s*Fi5wk9N}iyfvR3)rf3{R^4&QMw*~D=O4)M~+P% zpG?2sdxyP|QE^mXvV2K%C)iS%C)h3+F_~~$a7-{3tvGU~3W6@bV}h-&lWr=!Q4>tL zC)g5P86|^eFg}=iOsH)KTMf7EfXl~d)HG`+!G5v=w*1>bAPrkT;7+-Pb#KI2Vl!1w&8 zOf7a$h&lqc`LKgx*p>82ZePw|?{G&(-ezhtgQ_jfv#8jPrLx!>y9&0aq9+rwTVUIQ zd8*VrGc(KP2+J==@!ZLPCS&bjOZX)qbE|kfFnF%K68!t2!F~S-V;x{i6_!C*)!<5y zCDe9;Z71LoNEc&C*;Z~Z0k;!!uLGZU0H*0vXK2tRY-&ZdGlf`#tA^Tku+`7;J=ei( z`(y6|t*YtO>AfEVTY~O&+xKTa_Bo-JpMBG9y#?FGu^2dkD!eXW??Vro<|?@3!7f@H-GiIP?x?gx%v z%N#I4PcEGJ5C5(=I8YH~C`F7H>BI@Gl1dgE>wM1kaWL}?bLj~3UN_2A(A_Qp*HwpY zcY0Lnv2zzvU+dgK*|{gLVGmobQ#;sl{i%d5r5wx+WPn!z*fO;) z(YJB<@|mg+mR34Z}FQW53e;pLF1K7nwAv$}xo_|Pz>1#BGwTS6^+(`vBQDxQMccCZbgHXa7| z6<^Q&t-v;kx3iOwy600W(p-N*TYae-T%@;yEmc?^pC_pN_=BjUO#7uXDlXLfgUyoT z=kl_Fi^~Si>gvLu)yZ-!Tu_--2VCRraT9Du*|YcG0oYRAZd~BzweDvGRqH#~4;6bx7H^D)M-Fb)ltpnA1FEB zG3}aQ8wAs?Pmi$q;w2W??>6LOJ~0SX)&bU@azF6A!E-40>81Mn$KSD>2xP*G%4kqt zaD0IAzCLw+@#ttC?60^b&guE6i9AibBCfiikFwU^K`CmX9C5H5W_S|3U?;#W#@WX@ zi`OF)z#hwE)H?BO&hLraDBD9BU!;6B9Vb&B+`gk@tUVjWn3ch-Gk{UI57>Mq6P5hC zrm(mLwi)FsXN6u1Jm{Q|UvT2W`O0b6lNjybuPyscrrbNQ|Nx^6fHIw-fR zwoJ9YDcIfg{kLFyeU0v|V%wpBHbL-Ddi*9}tKhW-wS?PSuvHiCf5yMO7*QalE_(&1 zbdA%0K`Js8TY@bCn7w8Rx2&_JVp}!31kB$9Tc(4a^YTkw(D6b~z?#=$ycVH2*H9|1 z;4f#~U+qX664q>0yguwdZ3kN_w#rtC-vyV;Xo0P|gs9gQ*lxW13Aqf-Xl#KrUWjhQ zognmWjw-ecOZu>~7b|1iV6ZI@@5k_afo(Nmpq#L<=sDOQc@coEs(Ym(sqj^eqEPZe zuin6ALtO~5rVQs-!8V^xsmX*(?xAyBFs+t5CjfrV^z$N5COR5*fm_*!1lyxyj14QW zrJ|<#(kig!ZK^m5cyyYoGLTaBwPCEsRdj;wL^_E#vs212ieM|qsEz@BkgjHmlRuw^PT>q=KbF*&{}HkJRlq`tFOnQ%+6BDkvbW968v)Y(=V@~;6~ zrK+|RMJ~4;=Gx&_DT*z1m5|HFxQzDDK&!{r_pHC~*2w4hd9s}Ml;xJnsex95qy|Uc zXHDzJYILuIas3!Sm&?##ssWUbX?WH9L*M6fI`n$z_v=wV{_93xmdAA=*z&x=Ndl$V zrd9o>q}8j58XnJ_M3NMD$y(_ETh^OXY2Dt$vuqYGl4-n5Wdz>vhG46n=Wl}L1UzLj z)bE90OWfhFn7#w&VpQ~cY+NRR7VRWxaK@g%be3NF6<|yEXV%p!#nuITM-yxXZeyN6 zEtlCD8gA(p-X2Wp)gg}?NhvMZeey!p$Df}nuLaRoxs~l;E2oR#oS~FkPTH-Hyu_T7 z!BoTr`?ZQe6JeHMs}OvVwQld zz-?5i(gfPou!Tyt5hhsZJ}*D*y>bdw)oL%?Z?2D5Zej1 z`aXg5IpeGRpQU{QMmuqDiLc^Ycc-)gT)WfL1}QhFJovg4tkO(S*Ic| zaX+!fmisB;;LX^G0xVvP)zv=Y@2oxLTFUYoEwGhTW8wY z&zSZbC4xQ^$wpp?bRc}p$lSTB!6p%?t-6i@rVygn7VO|fkUTTUpnBB;4NQeZog>H|}e zY5cSnvrz4gVBIiO+a))Kf*(iTw@?gJTMf1}j$*4F*3;4jS=H6Hk5^%}9YQtOYG~^m zHPq>m@YNZ7uJe8E_o>!h7g}A_%kCW8m%-Z_Cfi3o&U9_oB7Z1E1*H;tO%NctypI8` zUN5~q`t_aAsvmD(zhAn|WhfIXwO_A-tt-d6s)yw{ssT>p9C4zA2dFsWG6i29l4`z* z=_*GGY$4OxuwWP}71_41U|XP4n==_UmQ1JFf@&r1O06kXSE;KFMy=3lu+{2qb8G`y z4YYbB*yiF1OgRZ`J%6EGej8_j!BZWyR%%Xs@-)Gn6l9g~&jtU6;Nl1?<1aDk_hBr? z9@vAZvptv8vIbrR+z*niqW(@Oom5X!adJO88Z-}LpG0$iqA2a5H0{tx zKX?T#I8=(6zVPAo4!;{-D=^)bV0#gO?bhf|DD)>#bxf=oboq@7d~l@WuMVaiH^Yix z!)yj#Ok($u)V)3I5;crsrs59j`mdP&f5h0cKFoWpg+HT z)St`ODc0SNd5(Owj>r8eJW2U@mPumcrLI9$=2863(?MQp$;o#zb;Zn;HpNyH zzeBtln*unMcv-*tC$3nk70;$|eitxc9##3p`*sj`k8t_F`ur<nTm1sIbT)3nZK&N8ipEmc*WO+Sw;E^(t{P^`;Usii2e%q* z37_o>Y3FSXW}QH*@Bb3eYPi+QvrCjtV&9~1fO^k0;U+zGa<$E`SbQL*k| zHGUV%R+qHS$))3%9ZCYbHQ@44z?O+pL{h>l6<48|V4yPj8kcx0$#(m|n;MGj4{4gx zBl7KwAA!ajoZ$fHY!yVgSDZitf{_aZ_1$Q&J+JSJV!J)|GfD$VtT`5{v9P!{(*;>M zA}jY}s>~9eazWN^$gQy#>}|`Qx4*{y_+ziBvAqx-q=QuCdEdkS%MpMrdDwdAvLU-B zsG5`8a_yrIJY|N&2MD&OhuHhMrPy8t+f$r1XxbIDMxq&$w3$$8cm!M4>&jx8#&>ii zsmSeMyJ@IYWP&ZBmZnmw=F&vjQ8l(qMW$jaP#X(jhpIT0OUK3gV0*0O`PL6f|Dc)| zu>!Sxo++BAhp0UL0W*CGF#sF&T>)DH>-lLN_0vH9;`dLm)e{^+1~$Q0G6N`o@1EjC z_Df7B+gy?NT438Uj|yCC+o4u&2ddlQ5l)thvYe8e0bBX(ge`1#MX((;WO9V9l0F2s zRBM-Q)wh*3eL7m8t6;DRX+i2RA@4fHRzp|&sKHH-&1GE!wyoy^@D6(Ka=TQUBDN}0 z!TUO;S;KPs$Yt@qUM4@Ex7$ap{Hx(aSi zo%i);w2vBWsoL`ORBYb^Tecl*oQc5?p_XPpGO5J+dG;B-R3?M!IH&tJOC}W9{ydPv z}g(Q0Lvispxc^{IIy zff*}-ZTcqc?@5{%Tk@z371oXhtfx?QBXt3Qoz@(qTY}`gMVxZU?k&=SdNEFKv1ItkpMZ=cbVL~m{+nmAH zM@r4rwYIXoOhb;a#x{dluOF{pPBm+6si0C#2H%`KFDI~rQ*1q+z?6~2 zf;EV7rytnd6%yv(PcB=%mLNbC)6ixd&C*JS2-Oo z>+u6_$(;(W2GjQ1RSk|hO<2Px0gTQQ|s}ZjcQ>|m=^Q>~!> z+2gNOmj4r9_ghkt{~WMAzq#rq>4>y_3&9|PB4dTz~$hLmVqDQbDRbYE|p$hT>6;rcS z6Kv}ZQEcP_k7>Q9hj{z*&scIDEXFM?W-`F;7Eosb6z|Mt(~ZM~g* zudb)%V|=cCT{R5r_vrWO&sug=oiy+3RAj!EN-g1*?{C%E9?PT~Aw+rdp5v0ekfk>= zCzq7ACcjH&sIV;=`)t4$=greKAay(XGOGwoQP~|x5bd%u7Ak^w0+-g-; zrz?L5YWX-*d0A^YZKtsPY(&zgS<=Mw6!#T7))LkwTSCmE0>}-{?*efrC)j*JupPiy zG>InIQlXT6&<3?~LI{4t;!zOLAiW*MF6hkF!U^Q%DCCWBO zw!p1|S_QU*TkZpbI{WpiU~Op<^YIL({eJ9@u!sAhlx*=l%lc?h?-kFg^HfkPt#WC2 zUaSj@5^N{TEM}cSy!85kEd{nba^#IosO7?xa;p{F=43mwa00NMHwT)j$W61Q4kc4R zu0gULAUmOtiY%WOg;vshlR@398u_?-KUL45MNp7-Ebj|GyYsX3XL9WPOx~C0ds8U& zs#ILo<1PlV5KV#63ATEft9bY)hbtrXk$!S?rfoN&zL{ML~@fT@~(&QxTb zj{Irkr$FnkdCzADTMdl5*7eUG`T4pI^{+YJlR8_fuUDgUyOd(90auMTPeoS7{G2i5 zA8Uf`6pDjB3SI~`zZW&{o}_%Q`**=u^XUNFg*Eq{M9sM?V7p=8#g^BN74t4uk})g| zc&L{al*!B`@kAM9Nb(J@R^|NNoVpGEJp8!>SA&03RLT!mC}@z*Ka?^v{OkJIR^2G7 zZlu{CRZ>)&ZDgnl_M&F%=tj*}L1-dS{4TD@yhuMk5Le{+OcaF#!L1vsJ|`#`A&HvX zgPO}9k2pJ**{3yYW7G*_;j00h*UF+sT%7LV==@MFUie3x zLDrz4#_yN=Q~}tjxIJT|jN;#iG3pwa&L*+_lI?KzRGksi@c6!FFGsaJ*6(sgoGRtz z**%h$Azx~DC_w@;6iIN>;gTFOPvHZkiu z*n2So>>a3nmNas@(6x90uJKK2sbOR&|U+>xo&s$RAP zUOv_ytMQl^b>*xWCSoBh^d+%B@eJ6ms$RAY(H-P_=XcKwS_Tyj(VnO*i{fw!?CxOa zfa$wTT+lNLN}EwYxc2;@-7x#<~XgVtfaOWSu$Dz;x=>xCPdt7A#-d>x{GA z&;Gk+JtTpKzgcx`*KvGtBERD!vA-jT9Rd40!0B6{R>tIT1}_p8Mzcwo(81=0`kfyi zj4Y;URcZk*w?ejhjTX!*- zh%1v~?~d{M#}Q1qgLoYEF){E6XUjF<`~v6P_wu)x`<9X~_x!mEw)A4UGCdqFk5!M^ zlVki8Vf!N=xrl|8h>J={)y~#Jajb^9uT)BM&WMXzOQ0pBuZBESXdKn!qt=teYHw0f zUTKI_?EgDnkIn$QZv<8e?94aX56*K^FCBpH9?rnOj7&3^8M${S*#3DOFQRG8rN6`v zu_PL`9r>H^_SKHcbmC=DL#8B~De3Agb%}F2;&U?O-9B)5fuCuxW%Xkr0JdT%0Y>Qq zqkjIQW7v~r2yn=ytBDvg!TUx|*I+`N&J+FkBPg6bS63t}k=LTtG= zg_WKb+~&ebEQFJokEm#YZ3{qky|0X)4GP;~RKw|~jA}oAE_dYCagkETKiBCe zhsVm5aHYK#TWnn)ov&B-|6{;b1MZ(a{xxB?9a=kqR^M-b4R5~>wltl(sd?0UV4Ir> zz&6|gwqIb~|Dp|S130<`Tl`hQmT*g$typ0RLhTi>bwkLz5ls706u-WYv*nz?GwR2v zpC94u;#k0gB3e*hE7xlB4?*qZ0C=+{lO;@Le(A+9mGMyh=eGb2LQZ(`rl3aGW)fsn zWfd=A&Tx9P3!Lu*1h%aT4o99~WvCx{rqjk_0=72+)0@7xZ1Si#w8~5#s2$dH@{kN=u&Uz6{tqn7|;dT})G%NEzBlDk|zNd)yLg z+rd`S#!VB&IMqrEOHLd!Rs@S#A8(#~4^)ul*Dy#E3j+2ph*s$Zv`H03k93&9tS5S*yf5(zgva^TLrZ~DrQXVUONN0`jOtljq8w8-p)@?A@e%v5>RzmT5BoXu z^-?Qo#8EWjSh5V{Y=$X)bh#edomrb$aXq*`B}>7qz_O=QV;;|JbtOHVS@npvrbI?4|q$hjZij!RW=$ z@i3mb7V_VHjnn0_`mIZCZjhbAQ$zDVb)FE2BiNoC0xQc{`}P~D8(rW&lp5MNil%{l zEGA%kEx>*VY&#$SM5rYU6Kp5qz8JVwe|QX3YO04X*F89kb3%#uuO{>KgqPB$<@a2B zjoq)GV$L7Nh|`CW%rLgbrh!A2axmj1a6AscR!yC1(>y-M^XEPq%xu}&#!JVOzPfWE z3;8ay&Fz?Vv>I$xT{7X8+rbt;tf?i`u5~9RYCX!JXy&eq1$RiCjj_u~4z=zqzd7P0 z8Cwvs3?!J)LD_@-bR%3$dxansKi#rE^Tt*&+c^zl={ z)($}T`s45xYy;Qezb@cvknJ3A!M6GL{tvpLC(Qq=6&UA}O5|@7nT(Aw!Tj2E?4#%IO`e*2#GxZVV8IjL0id$E}8!CWGQxvYh`;S}b+9K^=NOJJWhbw|MYkx~`v$7nPdhq!DU zKw22_f{ile&NlYPN3cBHk3}mc!L;p-e}03rLQeIvWmX0E&E*j;F7|MK{w`Psmrpm= zLrD?7EEll${XbD29z@Rdf{TA%=$jqzs+8L6z?P}Ygxj(aQ_jhrjYT((dEds$mqR$6 zcn+*BtMo&vPXu(fIidTpR#~{dJWkFIfsHl19eIiJgGV4Vuyx72n?~jPCpcW5&nV6y3&B4eRD*Z!Ph!c8zQ2+@~gq@0^qGrTfz@`nD#0A-v z2?Hv)DwUOrsEYNtYR#h++Yf;)-={+>w%V9VoR_VXIN;W-6skdJ*saT`qUUN~_vn>xN+KP-RuhDV1n$gEpul6bo=$bm(mv8?pV$O3Z?! z&qmFl_E7;Y!A&cYgx=+dQraq^I4Y3I|ixb3NGZh3i07 zn3FpMaH_wnF;l==fR-(O;)HT#3dWXCIfwmA)7bp!3C>E(04JU#oq&dIJZGKZ@>G=w z98sa=xr*^_8|Re*sz3h|-$lCc+_UjK>0;{PFxEy#aK5oA_3xb2J3l^=Udc-2`Yp?Oiy0EZIi6|5Y|XW~i^Ip0D0>e;r{9I-eT@49$bI=8&Wo$S@tNB1 zd_4h|z^p?Y=Xma9R?t57^EqrjdyeOZg{hc>`LK<0)W>Sb5xAvt%VSBKNaf-NG}tor znC*Qu+_qHPw3sk08ht1aeuMqdIn}D?fMp{*UorKZfA4raFhyDe?K$vvA6VPP{_{DM zvfp4P){i-R7-MEX7KXpY{(K2IItPw}_j4Iix}uIP0b1E^)iUU8v4p)RtkumZIP6VG z3a=<-p9yLS$^_do*CkMHRoZgPO}P`82(MBj8_qy_*LEeb(v`$=cQV+Xb|o~`G_YC@ zF)dmdT3vzMn}X#{pqB5w>F58~f~{6?Z^8E3wmyGdpw-~o3AFmYeqN8aitX>sx3^%c z+>qJFmc~)5&Rx(IxoY3RnsrCU-2n?5eI|-&L(nznz=`U;Dhe4@GS+r7 zSbIsZ-Ce`RH^V4psKRukk}yzBS|~auwuXjq@bhEfh`j;Zg61m{dn%=Gy#Q1ea5(w{ z3IiUd<6S5?5v-+5tog=ggIWSH!M2p_K`|4;yw`)-R2cL99!Ap^rXKZUcY0jG?a^CR zd&iV&DmqkE3G5u-?c#EC4R0o1B0reMbhHbL(Jrib1}Yf`Be7nreEkq-g$3a4wwhF+ zdM&^o?0@brUPQjy0#=vt`o|wd^)32Wp;iZ6J$0MMB$vxLX3FS3@cIqbhQE^fL-qzGC=!NPi&u+TSc_5ZR6UYe zd#U@c)~tlQcGXE>+4Ch<9S=3j1A&(HtOP9f!zI`WvrPg ziH*1#d7qHW;O)(L3fo2k8)ia2ziO-WTBZcoY`d+^4$YC&^40nzQF4-?LisUO_G8Zx zD4Dv=CP$3iB%W4ci1oZAj`idk4qWb9|n+`I;*0og)@D zqOI2wMzu;!U}aFX<+=)-2EBFpU8?<|)b-}Rmlj3*j_hWwGu8GrOPOgg9eK(0B&Bu4 zbg=U6zi>{teaB<-Ol4xQpDDqHV8!1bkJq=ar2f48&EKWu;z^_zqn0J9@)PL{ir;*P z{W)e}@Z1)px#(0EDtBBSRZ7WC#`)n+!Amry{&ZQxh@}bkqj!s|HSF&f&eQH z*(;oV?HHH95nHS=&Ve_FKy?R=#R`h)e_$atfTh?F79#z~IS=rRskZmO!z+UFKEd@2 zIHcj*xLf5yB&fZ0ewl-fd z+wOm=VtWg=*8;6hdAtJpmh56x(T)<7HeT=6P7)z%xo=HoajOny1{gv~n zC~|HW%83wGQW2CA5iEKkEO;^G`;!%k;mW^BAjn;6g7 zn990%77t-Ioxohu2OXK0Gij84UsS5ibS7xW5~N)cPy>*q3$k)Tz8-AX0_vCc-f+x(TV5q&mFdWsvjOz9WlyGlj*dhiW{Hl^(*AgKaA%P)d*@oYtad zGqrfb^dz;I>BVby8Z|qOikHH2B874yCAZhy6xMCEE_$7)U=pZwEi9puu&V)nKn#dWe{Kqw;S;c)=U+0KjLFE>|-tJOI9T!V%v0{4y%FX=5R7DHqz9s{gD+Y^;TBtcPq=!!~Gqq#b=Z z@_sey$ak|IcH}jDk2V2fOPhk@Nt7-1*{m6+ip^k}b=6B@)eT&$1>*UgJ5p=R@09AT z)SsJ5VHfx}JgK!M+%CE) zOY8rcgl*vTFIG z;Ff)D)$?roqfDdNyOw~fL24~NC<^0JPfGg1=HvZXh-EPy&0su|!i+tDF*A!7RtC?V zES~%Qc;WWpSu}xX_iW7eB$4k*VKq94g*!f0y+;`7axr40F_9RO_l{W^j9MAIaJY<& z99vIaHI60v#2|0R$zmqVb4kBaNAEgV?sEPEz}7>#SJ&jKRAg;NMRj&LoWW`&i)y$Z zwNO9Sd;788-G}wAENb^M^7u-m9}IDK)=F+TBgYlL2Tn4yBKUqnKFVQV>OyZ;pL$gx zzA-5OW(D{2r6F^_{WgeY{cUG-fNfCg{r)6~2HDQ>`iYs_ROH)KWB~}&-v$+Ts-LBp zGcl`^&iHL+E?{$c8Y3yIBv$1~on+HI>bAxP4`gjEcF{a{QjE559r%(@nuv;5v2(J6Ro&+Bk|} ztKoJf8k5w=isxX(b){BvF>Z(gS9H=SI2j3nMmH@WIp-!Z>v))m7z$`;Q!>_Kr z)zI4swpy{}`m={A)hLdYu#ZaE#d5@#mM!_X3mOb*lOYAtDn(eWOFP*5O{Mc=%It@p zqe?37-C}5@K$Z@?0;f?I1P4xJEEpyhVm20{aWVBNgySgnT3GEhvDRxzFjbTWNPN#y z5WG!eAF6FibyG$^1hIV7mSrwE9vB*`3A4%&OMx!ol>1_l>k+fD$P9tNFo^3Zsn0y7 zSR-sIRi5A7nyFNIzJK2IF=cz0usn>}9;PHsIg16a4`qK4OYtO@qU;ZwL?xb3>)Oi{ zY76CV6DtuPtFa79u`HI1e&me-EX40)F*<}o_Yg`w!^rmxU@nx!Txq($WkYQibSW4DAXC^UkCNL9s zF>N@QHC!y3KJs=Fc{3q>WLKg|RH7-V&CK;WScuRVFo7BNw2fGpU>$GF!KC41ChlQ2 zp2S?-2lvga;o(_V1Y;4EemohqRf&V)VlHA!4KUr0`F(T0snAf%(F%;S6xb@bRsCyq z>T9t(fs&X>rBR6tpc);Nkv(MDYNi-bMo!a_G$vzdOqqR{vHLL}@5f>!gF<&2%iU?z zLIYU*9~(9E0p=rVY5y}C@0T1Ko|M!J=R#?zb)~{9Dav6&Z?-wXpeGt+(jl09;3Nb;^A>DBeIL9Js-58aOZRWV z_M^(HR$zbYc&pgnDz=}RqWs^UihLDp?}B}8m15fh+YS2*NlRX~?jmn>W0sKRM=_JO z#7Ky)sDuqFHmv7dOr#_Yb}{K8mxyDz&%%=5gOzLqbMF6Q#<_!BUkqbj7v?hta();^ zHzZMZLs)h~;>awfR(1$GDGTd#owh=#xe!M?0ZlDh|d0I%hD7aDSt-I;=V$12q zy4@{K)@476QZkNm%EWTg7I>x`b2-w5btjHWJcgPT$C_=TX2h^*n%MO`Y%>+Lt;LT{ zJ^n3V%lcA6vecWh53!_uQW2!m#hS#VsGbBa)_$_DE5VP>vQW7D+W-I{07*naR0YqCRR74_lE0Ho^{ej0CpK zq`(N3U#2COOsc6#6x<~8UJ^Mkjl7=;B8!D&2D9v&nNZ&`e*^riRo1e`REq5{gRL*M zy-ZbZhfuAu60juo*-Bx>$)MzBQFOCd@>DFleOPw0D0zKYN@S5sX0ez`ODrYTy0gAl zE5#fcIyG9S@O}thKmNGaG`Cu_vRJp$*otSdWu^mVnRUS#IVP6PluRyE4XWY^Y==|W z4kxf3O=81H%5lVgz(q&xYwm9bdkc%YY^PDO(CdYY3t(a}ajL#0XD_>Zs-Sx5F zlR_<=7PYg`;~>{Csr7oEYWb=J`uo) z69R2}=ypF;1S>{XQhrx@5-8vGv2xc(9f8))dXU?eeTq%j*$V>*_`jFG{D*)Q8%Fo#eyhfp#GWrAnc=)-ip z53{k1I6c$INg%jaIVS4~210CS+$y%84zzkQ;O1c43BDbm`(FL`tz!GDK=>AHZ^8B! zZ0RigY3+VkU&}OF*4S30##YtWu3Jn;{u@?f|BH&)ceDf_U~qd`d{p0V$toQ@#p-bLQ)Mlln^gxQ6qqyfV0 zYSX-`2Ww^z)*0~-HiOtO!`Lt*sG4C^Z3VKcHdA$J9`$*__LUREdZZg$b_^SygT+V) zbT2KX`>>G8B0n&U{NQ~Qh99Ez@DWxXeTC|mUt;acN2vV$5oR9@V|t(;^C=Idq=lLn z!@AXrb+Zd=H1cvISau^Qx>1zum})^|gt29W@yd$fm1m;Vdk5867`q7GU zMng@oZEx+P(~vt;k*`&3V}=+I(S(SAyBsmFV$fKM>Vu25s0-B_H6f|9OaYZT)wnB= zz*@_)5to$Dn(IkTBLS2~KpPG(94#!z;-FCw9dv2%Bdu##x0zr{AJ$Q)x!$-(J_)5mb2M>`OzK`O-uzcq$eny~} z>8`9H?F3s5m{evN1WbZwC)o0R61HmhQ}h&2&nL5(N%dngt)e*eC5pojk-z_?tlRv< zhnRo#0E-VFAb<`QY-2#BnwZR@wI0r%tJs_Irh^ct$9m4OFX9(sV)!AGbLKE!(e zBdiZRM795+dT#I`%7gb&>c5Y2|1efE!>DD3v6;M&oy0J<{UK~622e{6U?n?%V*h}o zrRN5Rz$gqoKyg65pUWup56f?AvHw1D{X>!+K)5BuGKw-P_?`Ds@|s0{e_#C_#c#er z>DzBn{QE!T`&$^kkGa7?nOs^(rzOpOiH28fp%XSFSm(>MZcfs0vW5z7-ta}SUvv5d zPhOO%$79aq|}j8HCzv+u@%l@qdSAz-6X2_l349lEo%s}OFgPKlx=KSPrBBd z!SWpsbpB;MDQjcryIkqdN@cs$<6@=Tk+Imz{pBJTb_HY!vjlo7wX@xZ^c~LKi-VIx zY)@3`vOYW5a^K7T4=1n~O<*pb#I%{jxSf`?@u|#x%=A6P{NPu}4}Xo~@V6)re}~f0 zw{m-a;P060{|XD4hsgQ&Wm2aUWm+;7-k`TG`{>H?#A8YYq4pMRZ^8CgLE>*!OaBvI z|4U$7@xH(x8Nc-Tzx=#5i|QP;X_Ov6k9kzpy^EUr1=hU3U1|5T?scnPsQ(w+{jf1S zb|k^kA7@E`xmgz zwiSVK5#47`-YIh=wpyVJ@CnU6_N47h`(hS;g+CXbya$A-gmH=N@6OVLH_H1 z;O*Qj@ah$?zo!ggXfVTI3mon%x&_maW_K5tb2Hfa<}1vE*dIEEP2T_&VY)uAIB|hH z_9kV`>qb0|-B=7eMnqI%rbO4Qhy+#RD`8U2jiF*iC7PB)pO zQMGI_-`R{g*orbd@U}8e(yCXhpC}!Bm3ftNTUPCa>^28osxQg}h^9mgW&>y^Th&U& zl+Wb)Y{qO!m8Ju*^fh&ZktR|dp_bD!7$SI!u~6K>mYooH-kOudYJ%#5g=x>j=D&YH zBbNsb*}jDlm`>4nihU(%V8d~54_IHr?&GI;_1*WP(i0$A|0|!tRy4NLstRO1AR?O?`BV(HPB*clxIws(|4m#kB;9%9nNbqkEd-s}Q9Td4i( zdn~5=0`nmk6_@I$FUCwXyZR8c{+h?BbWVKz5V^@`IM}MHa{^tk&x4jrbfd2GKKqe! zpS{6BrHt~+Cm4HhAJhEELl+)@j~OVj}KhD$$R^qwlc$ zVhUJ$0~`W4paD?>I1NG^!RZQ4V=6iVpCI>-uQBQ+Fv;3+FD2lv0gW~41jg$?mXAxy zcV~N_j{7$OTf(SLMOEpjIyF|QGD{H~62W>FBL*0yaC_LGa@)Qh&G!ZG=W~2bIizBx z*9K#i(ZiHn7c0H4z_F;BQCCvVnR-5NsFZc4pfi2FxzEBT${|zU$M+JHxjpQ)sh2^h zriw~+n5n%4xRqW{Qh=-72{3A1YGf+5sJelf5^pp3xDMXe>MS9Usu@3<6CvCNZr`=* z!1ai#_2T-;eh=1{>-1-(9bfx7y)G8JOo8tOD~U-nA-%=7o{ivmsR-<`Z0krFebIRB z_!2m&w_^7#PRmtPet3ovGb0LbE}BI#nvqEYtt|3;peKTSC(V7~As_O8b?9aNzT-`6 zbZ-u)H`$)wU$NB+?k_2~A3ttyYiw_8Z2!<2+gq?@jWY0|8r#1z*h(K;>0wJ~3`@E% z;gYH;A(u)jp>{D5#Z=nB-qbUkt}X(HyQ+N+9e(SFsN)dz#wjivXQ)d{2exP6h3r1g z7N@cO@4qAGgt3`r>S`EN6E_V*0FC#VcFb|jB*3cJG@@V-XxHL~1Qk1iOqu;F9aCyW zS3YCA9|HA?6~T&Uf_*aQeVS_Z3Dj;*P2qfJ2aQ7lthPR7XIAznWZRxINWV%t3G)yB z#wP016If0qQ1$818wsF44gxJ(%CKK*&164P3%k)cb__zRa%ZkMYGOq|o3P!C7^?PF zuqE8CnAd}??q#cMY&F#CQTGYuxNg`1)GD|Yunis;$JqdYsqSj1<@eVNscTdwKdghL zL$9QgTAtLa5^m+O!10#LQSDr80cZj?!M77^39>r)yn^FaOBfBcqN>Inr4~Crmiz=J zJrDUWAK_qO4tV`40HMI``+_Zvcx>~2FcOfC4pA?ba4|W9vCk!2BXPZ$u_0};f{~A% z9^!a0huU}lk`_x#REYzy6-Q!Asq4Q6Vy}D6Y{El+>NyJQIlMjD#f9{9J;fysrMv3| zj@gMC$I@;2RGvRNdX3Fm0W;4ZWAw|17**L%^0jc?q^uaia=sb8I^*VhB zY^yy4Lj|{lQw^pBS*hy|#!j$RP}_oI4aUv)6OJVUpy~izg1my2rTM}-yCet3>qhbj2|D8y7N9quPi0;rU9m6p!$ zMT34mf~|MwKT`GmWkpmgp8u(1r&6o$cdqZPV*9Bn#~*s%2WxB_{~d}g z!B&9QRA8&1HY9*c*ep9?F*Ksd)7IL0~7a3WC`BQlzi@tTcI z>*b>RWFMEgDJ-TPtY#gox(3!gQ|dvLQ4y8Iu&A+AWY+{_TQJMlD0NQ(5g|oG3*q+j zf^AIdTi2L2>$zegG~d^cwWrT;vA!Af=dH`($G_vm+EX;Zy>_BHR;rW$_VGPYy=-^B z`5LQ9PwGi4wt`v$tu_}T_^<`dwqaq5y;hwFN?t3NwoDaU?H6VfTm{>vavKlQnmgM6 z5Nri*16O1XxOybawg;6{9qo^|z*Z@=%D75RN;D@Xq_1cIvu3Jk%B0MhXwcLGU1bVH zrB%7w>XheZ?^a9oD5b-#Qis(@7;aaXHIR$qYpB;quT`nT^rYT-{pC~O%~sHRm}YSV zp))jiWD_WPpS^n7vsX$0PL(RZv5Ad;d@FU-3d-$3t>yRUh*4CtpRLW*;Pe%+RZhvO zuPwiGno1SZY0RWkSpDI9Tx?WSUtpXI{;=z5y}54efO;NuLRFnn1?2YM;obN+mih*z z7L{NtZG;R5n>Pg8IX{7utr`xGUaQF(_ORjpxm4!|b+mI`kJY~8^W0y@2iVOoVe-*e zcTcr{7pHqbBiR3XU-SLCPckQrws!FD@iXZ;OVgdX)BxT+ z9|gA9j*P8%js<8r@pdMdeU4L{%l`@>gWjl|fZE>1Y+t|BC)2^1W@qe|+ls5IEtOg^ zrlL7jGh8UR^+kndU)7OB8r8?ofQ@Yhv;4hZG*Ca|_tlVd!ik(0xTgrW=cw~oyFA0i z<_1=N{7GDYCkz|Yy>ZO-#8C)20zgz{86Q$^J3+Sdz6Qrn83~>W{xk$C;Gi;kHB98A zS7R||f}vk`9n`jiE!R(Kayyh;s1qKhwx@$M)l97qSpqIJmPsFrZW>7^)p;j4J2$)x!rqC)wB?Q zC~a}czM-c$pPj?}zye`?*%6$6v%R)5gc_;9o;)-U+JLN>i#}v z1_s3tY~Hd}58f+a8^4l{%(P^2RgRm|W0rkp3A?RSWV+lYBn^4%*%+|Pl7ygNE#a1b zfa-ML*Qzb2CU}gs6kBEkY`q+ly6UNzgPD+}>PW+`)UPh}s+405w(aebc)Js1JMVuA z(CYUPyfpA>=+nxmhDZ&Wyid4QpsB|e0P}U%h5oG0QA6%^P^g!qKJ)5la5?(D1W8F} zz6NahUIn*T!B)1Dz}%)95-K&oUQNkXO6XOPY8hV%7`K7C23xKl*Hdjrn>xwQjCfb# zvjJ_O`qIp*6ibSk8rv;R4GsgZw&gd~Xij{e;}DlP0w=#YvCB}`3;R5W@;7~cDgA(- zMtm`nqDwNtmWnM6wFtFz)h5_--*ew^AKilO&A|M_K&n%Ue`&l0+do9{y;W@gSo5gc zROJ8TsmOMZw9jGcv5tzZ(vay^yp)b(+>c@EeinE`74k$bQcvX%QXoU}I_v^qmJwM_ zcupkB3#BlRaD40&Y~LONC)^>@Z%eMn*=dW{;v5^nb*)ZPmUQLg zBkVnUifUg5G(_4+xNVAGt0hd;aa)2Pa?8a5AAy>h!23tLHUlMM0ND8$T zd2b>?Pbg@WoFm~>M<>K;aMjNf7~5Z?0a7cgT5(r(u&U>5OQC%qXjLk*YTcr1aJ7>! zRneU5V3DR>ZNbNMEV+)fUV492wYWT%=+<0LCNS%{Sa@(B2ZhC^(nsXD2->A7owR|= z#s%v2x}@D7A0MiNpMbl+hpnG}LN1*`!E==fmTRFTp+Hq!vFVKMrp5JD0N1%%W2=5t!u?1Qk^(x7>Gi1>zTMlSY6%Is#75fz4NV**A>I^dP1( z16X_d0(iyR;UhFIco|HvJrl^|WP(C?1%Y*Ni}|~{lr->@TprWIk1&!Mz}Vn@T&`4r z!=R3~LCDvWZ~CH|6H97xiEAnUaVGBMOfJl)6KTwuG#pZDtx81>l-u??Tc#w(Off%O zjeu;)iW!6!~)5v>+c=vc5c(t!;3=f&g9+)?@*Vl@nL!cmYQjm)D{vlpJ zAHzawK-%2UOsEh`h{+O-nLanzYGtz%Xj>qvQ)U&6Q0Wx74N`q|>T)Z!w)OfCJ;wLw z=QO11&(lzQ-Kbw9?_qtggi>w^l^QJhI{khP$Fj~%1-Ko|Ti_|6+N^z5>&SI&uM5@d z&N^9%Hqh4FqSsGtW2?qj0kQ%a0w3dZgKeS5MlNJyHsWB?_AxX30C@Xae#aN*NAmmC z6KwN?Jp>{wZvWgk#Tdd)~Uyx<83OkzUKI& z##_afyIK4Q<*#$3HTVTtKB9_hsS#|<$ za^Xpnq`ggy4_cVXMlqibW6Js)@=4X^hwjEwXG;~)4qq{bq7$$V?c__dBi4vE0qir@ z*b3Nc_h!#R!H$E5ItOFp>cW~A@Kk6BvjNZ&YDIJk`XcK;_Hxnx|FicV+-+P*xAyz* zzk9zKOJYE5pwZok43aE+>=|cSSZa*WrHA7Xtni7Fj{EfX6dD%+~QR@d3CheJ{~OH-(gP*5q~RKG8ThFUHO zw!`r$VEZ=Q4!~7Gt0DEX8ie`SZ^5kwTdK9v_9(1+kSe%kZLOPv%rs;%lhRAp+fs=g zESV}wVAT-IrM~|z$PNHko^QEe>-S5lJL_4O`CfPL;1LRV1Str6fp|)a$M13t=rnG!w+oxhAE^w;=mubm_TcyZz;)2JV z$D4q>WSQ8x{|oTuHPCLM*J`5K?Ma!Md>2 ztoIGCT1p2Njal{;52fs|^EQ^IzeL7KAaB~@q)X$dx9V))1GaSiCfKff4QzNKD#jh@ zH_Fy7rN|WOkC%W~G_UFc=S_48vHV<)@Cmmxj^blF&02%)>qG26e1>dv0$H}e2}H3< zS6n|^y(rc8DpQfQvZ+B(1BV7h1&{ABW}@=gPv>vbFkTRzUu?(Y{@o&DhYT})@b z(6{xf!ItMCU91yOJh4pspq#>66=U9&A!=d9Io9tVAXF(v;RY%dSD*I@e>t+D-gLM`9>8f_y+c@ z5v&?Fup0HFG-;t*&541D)C##XbsS*GKteLgT-k~jwk!Bgk7uX{a8_RiW?FR+YWq)j zMZPJ$YuUec-F!RN%p0g!x1`0-qUA;Y-URSwPnkls&(Uc&Ww1%*k;k*m@tK=y%cUAD zQc-yW9Pc5W44@eEVlD1LCGaLKY!eLdhtGg{t36D zcAXvJ)ua2^oQR`F$78x6hk`ELhLnkvtH^SDnF>vpWVYgA@HT_6tAUq}$_(uy-CweX zI^=zOlE6@t2Anw1Dd2jk!F4#Dm$$VN%jNLjsM_kZW!~0CO$1YMJZ25)P_Ul%qFI!r z5gX=E&8(r|R+M{{ZcN3IX~{ZN?X3kaC4y%EvoETXT;DB!P=e{Tc{3uded@WKQWl%6 z?{u#Yieu5!7Y+A9#z7mwtw*=r(>k`FJVG{=6a|@vVgj|C^dQvQ3Tz9ut$N}{;sUtr z*UJ8_I@O$D%V3=?;h(_$;+Olt0hJKeuD7{b>LlWN$hxQtC?D2;(qMbAoI_^%F4Am^ z6S2iiYgNvZ&}X?Ki(=d2b)bz-rzHwDCjuDlZVSxnpynzATLLSuvnQuOoo>V@coLt+ za`ZORkreiRc?`ThRF1&ybF^D$XmuLuy))HXe_QkQ`bwst&X~@HA#($Q1ls1N{dJO4JOW=^&RoB#MV??Z;qyQMo!coEm!ditVb;LD6H1c@*8hpV=|skfv=XYLceclIww7op|kZhgtG{qd~Ge zE=02h95pfLk0U=8L-l49>!WdLv&8d6xgsmopZjcWjE>e}utn16f$bnQ{QZjVZ~dL$ z$Lktf_8opVhR;*pzEEqc?|;C^OewbZ-&C6KpS`?d*!>u&yarniboc|R24Ip0$+{kQ zJj7ZD{X9N`3r2@H?U>j!j?S(w)@$%*k|(www)1dngrX? zKG>Eu*f!~$%b9nT`o-amd>&VT;V$&uKYKYya^qSt)IdnDmn*oruE?BbJOz4npuUaD zFJD8sBEQ}0hYq!D!J=Xe8|D}`!#YN=8CJo+Q-Q4Ao&e5XNrjwp#dKGNrD_60_(FcI5+L%O1BmYZOb42e~hk!2YIc?bAF%x5JrOrPFXd82pja zKU4%>Q6QK;d9;rO$A^;T!CoSWjo=Nuvb=b~_Cg;3Tf!{CmP-Y;9)VtEG^HGr#rWz< z!Pbl2s2|nf4OAT;GSL8@#|&)GJ$7p}dDip0r_L-chX>ZY|GLAPKYj_?G6}T*_!q2A zB~c0a#9)hHt6-JNE#X$B9P2hm{JREQ4YyQzhryO<$`vypp_Ok!tp-~Kvcph2q=>s_ zQo~?NAk-o7=^8fa$1Wbq4*#zdTfQ4